Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как преобразовать short[10] в char[10]? 
:(
    Опции темы
Proger10
Дата 9.12.2009, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Код

typedef short SAMPLE;
SAMPLE *myArr;
char* myData;

myData = new char[10];

/* тут заполняется myArr записью с микрофона (PortAudio) */

/* вот так я попытался преобразовать */

for( i = 0; i < 9; i++ ) {
    myData[ i ] = (char) myArr[ i ];
}

/* 
далее myData я сохраняю в wave файл
само сохранение 100% правильное, проверял на рабочем файле. Что-то с конвертацией.. данные в myData наверное похеренные почему-то..
*/


нифига не получилось.. В чём моя ошибка?
PM MAIL   Вверх
586
Дата 9.12.2009, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 8
Всего: 146



Цитата(Proger10 @  9.12.2009,  16:06 Найти цитируемый пост)
for( i = 0; i < 9; i++ ) {

не всё копируешь:
Код
for( i = 0; i < 10; i++ )


Добавлено через 2 минуты и 35 секунд
Коли со звуком работаешь, то наверное, нужно старшую часть копировать:
Код
for( i = 0; i < 10; i++ ) {
    myData[ i ] = (char)(myArr[ i ] >> 8);
}

PM   Вверх
586
Дата 9.12.2009, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 8
Всего: 146



Цитата
Для файлов RIFF WAVE при способе кодирования звука PCM подразумевается, что шестнадцатиразрядные числа имеют формат signed, а восьмиразрядные - unsigned (с диапазоном значений от 0 до 255).

следовательно:
Код
for( i = 0; i < 10; i++ ) {
    //myData[ i ] = (char)((myArr[i]+0x8000) >> 8);
    myData[ i ] = ((char)(myArr[i] >> 8))+0x80;
}

PM   Вверх
Proger10
Дата 9.12.2009, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



м.. спасибо!
">> 8" - помогает проигрывать звук. Пишу в него голос, и он в файле звучит октавы на две выше.. smile
Не пойму из-за чего такое может возникать.. но файл уже проигрывается.

Добавлено через 6 минут и 24 секунды
звук 16битный, 11025 дискретизация, 1 канал..
PM MAIL   Вверх
Proger10
Дата 9.12.2009, 21:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



кстати, если запись виду в 8битном режиме, то на выходе файл получается ещё в два раза быстрее прошлого и гораздо выше по тону smile
Пом чего-то с вот этим сдвигом..

Добавлено через 4 минуты и 20 секунд
и длина выходного файла равна нулям секундам..

Добавлено через 5 минут и 26 секунд
#define PA_SAMPLE_TYPE  paInt16
вот в таком формате звук у меня..
PM MAIL   Вверх
Proger10
Дата 9.12.2009, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Вот полный исходник:
Код

#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"

#include <fstream>
#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

//#define SAMPLE_RATE  (44100)
#define SAMPLE_RATE  (11025)
#define FRAMES_PER_BUFFER (1024)
#define NUM_SECONDS     (2)
#define NUM_CHANNELS    (1)
// #define DITHER_FLAG     (paDitherOff) 
#define DITHER_FLAG     (0) 

/* Select sample format. */
#if 0
#define PA_SAMPLE_TYPE  paFloat32
typedef float SAMPLE;
#define SAMPLE_SILENCE  (0.0f)
#define PRINTF_S_FORMAT "%.8f"
#elif 1
#define PA_SAMPLE_TYPE  paInt16
typedef short SAMPLE;
#define SAMPLE_SILENCE  (0)
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE  paInt8
typedef char SAMPLE;
#define SAMPLE_SILENCE  (0)
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE  paUInt8
typedef unsigned char SAMPLE;
#define SAMPLE_SILENCE  (128)
#define PRINTF_S_FORMAT "%d"
#endif

class WavFileForIO {

/*
13:12:22 waveIO $ ./a.out files/111-mono.wav
myChunkSize: 59726
mySubChunk1Size: 16
myFormat: 1
myChannels: 1
mySampleRate: 11025
myByteRate: 22050
myBlockAlign: 2
myBitsPerSample: 16

Summary:
 Format: 1
 Channels: 1
 SampleRate: 11025
 ByteRate: 22050
 BlockAlign: 2
 BitsPerSample: 16
 DataSize: 59690

*/

/*
     WAV File Specification
     FROM http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
    The canonical WAVE format starts with the RIFF header:
    0         4   ChunkID          Contains the letters "RIFF" in ASCII form
                                   (0x52494646 big-endian form).
    4         4   ChunkSize        36 + SubChunk2Size, or more precisely:
                                   4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
                                   
                ChunkSize == 4 + ( 8 + 16 ) + (8 + ( NumSamples * NumChannels * BitsPerSample/8 ) )
                ChunkSize == 24 + ( 8 + ( NumSamples * 1 * 2 ) )
                
                ChunkSize == 24 + ( 8 + ( NumSamples * 2 ) )
                
                ChunkSize == 24 + ( 8 + ( 2 * 2 ) )
                
                ChunkSize == 36 + DataSize
                                   
                                   This is the size of the rest of the chunk 
                                   following this number.  This is the size of the 
                                   entire file in bytes minus 8 bytes for the
                                   two fields not included in this count:
                                   ChunkID and ChunkSize.
    8         4   Format           Contains the letters "WAVE"
                                   (0x57415645 big-endian form).

    The "WAVE" format consists of two subchunks: "fmt " and "data":
    The "fmt " subchunk describes the sound data's format:
    12        4   Subchunk1ID      Contains the letters "fmt "
                                   (0x666d7420 big-endian form).
    16        4   Subchunk1Size    16 for PCM.  This is the size of the
                                   rest of the Subchunk which follows this number.
    20        2   AudioFormat      PCM = 1 (i.e. Linear quantization)
                                   Values other than 1 indicate some 
                                   form of compression.
    22        2   NumChannels      Mono = 1, Stereo = 2, etc.
    24        4   SampleRate       8000, 44100, etc.
    28        4   ByteRate         == SampleRate * NumChannels * BitsPerSample/8
    32        2   BlockAlign       == NumChannels * BitsPerSample/8
                                   The number of bytes for one sample including
                                   all channels. I wonder what happens when
                                   this number isn't an integer?
    34        2   BitsPerSample    8 bits = 8, 16 bits = 16, etc.

    The "data" subchunk contains the size of the data and the actual sound:
    36        4   Subchunk2ID      Contains the letters "data"
                                   (0x64617461 big-endian form).
    40        4   Subchunk2Size    == NumSamples * NumChannels * BitsPerSample/8
                                   This is the number of bytes in the data.
                                   You can also think of this as the size
                                   of the read of the subchunk following this 
                                   number.
    44        *   Data             The actual sound data.
*/


     private:
        string    myPath;
        
    public:

        int    myChunkSize;
        int    mySubChunk1Size;
         short    myFormat;
        short    myChannels;
        int    mySampleRate;
        int    myByteRate;
        short    myBlockAlign;
        short    myBitsPerSample;
        int    myDataSize;
        char*    myData;

        void setPath( const string& newPath ) {

            myPath = newPath;

        }

        ~WavFileForIO() {

            myChunkSize = NULL;
            mySubChunk1Size = NULL;
             myFormat = NULL;
            myChannels = NULL;
            mySampleRate = NULL;
            myByteRate = NULL;
            myBlockAlign = NULL;
            myBitsPerSample = NULL;
            myDataSize = NULL;

        }

        WavFileForIO( const string& filePath ) {

            myPath = filePath;
            //read();

        }

        bool read(){

            ifstream inFile( myPath.c_str(), ios::in | ios::binary);

            inFile.seekg(4, ios::beg);
            inFile.read( (char*) &myChunkSize, 4 ); // read the ChunkSize
            inFile.seekg(16, ios::beg);
            inFile.read( (char*) &mySubChunk1Size, 4 ); // read the SubChunk1Size
            //inFile.seekg(20, ios::beg);
            inFile.read( (char*) &myFormat, sizeof( short ) ); // read the file format.  This should be 1 for PCM
            //inFile.seekg(22, ios::beg);
            inFile.read( (char*) &myChannels, sizeof( short ) ); // read the # of channels (1 or 2)
            //inFile.seekg(24, ios::beg);
            inFile.read( (char*) &mySampleRate, sizeof( int ) ); // read the samplerate
            //inFile.seekg(28, ios::beg);
            inFile.read( (char*) &myByteRate, sizeof( int ) ); // read the byterate
            //inFile.seekg(32, ios::beg);
            inFile.read( (char*) &myBlockAlign, sizeof( short ) ); // read the blockalign
            //inFile.seekg(34, ios::beg);
            inFile.read( (char*) &myBitsPerSample, sizeof( short ) ); // read the bitspersample
            inFile.seekg(40, ios::beg);
            inFile.read( (char*) &myDataSize, sizeof( int ) ); // read the size of the data

            myData = new char[ myDataSize ];
            inFile.seekg( 44, ios::beg );
            inFile.read( myData, myDataSize );

            inFile.close();

            return true;
        }

        bool save() {

            fstream myFile ( myPath.c_str(), ios::out | ios::binary);
            
            //myChunkSize = ;
            mySubChunk1Size = 16;
            myFormat = 1;
            myChannels = 1;
            mySampleRate = 11025;
            myByteRate = 22050;
            myBlockAlign = 2;
            myBitsPerSample = 16;

            myFile.seekp( 0, ios::beg ); 
            myFile.write( "RIFF", 4 );
            myFile.write( (char*) &myChunkSize, 4 );
            myFile.write( "WAVE", 4 );
            myFile.write( "fmt ", 4 );
            myFile.write( (char*) &mySubChunk1Size, 4 );
            myFile.write( (char*) &myFormat, 2 );
            myFile.write( (char*) &myChannels, 2 );
            myFile.write( (char*) &mySampleRate, 4 );
            myFile.write( (char*) &myByteRate, 4 );
            myFile.write( (char*) &myBlockAlign, 2 );
            myFile.write( (char*) &myBitsPerSample, 2 );
            myFile.write( "data", 4 );
            myFile.write( (char*) &myDataSize, 4 );
            myFile.write( myData, myDataSize );

            return true;

        }

        char *getSummary() {

            char *summary = new char[250];

            printf( "myChunkSize: %d\nmySubChunk1Size: %d\nmyFormat: %d\nmyChannels: %d\nmySampleRate: %d\nmyByteRate: %d\nmyBlockAlign: %d\nmyBitsPerSample: %d\n\n", myChunkSize, mySubChunk1Size, myFormat, myChannels, mySampleRate, myByteRate, myBlockAlign, myBitsPerSample );
            sprintf( summary, " Format: %d\n Channels: %d\n SampleRate: %d\n ByteRate: %d\n BlockAlign: %d\n BitsPerSample: %d\n DataSize: %d\n", myFormat, myChannels, mySampleRate, myByteRate, myBlockAlign, myBitsPerSample, myDataSize );

            return summary;

        }
};


/* --------------------------------------------------------------------------------------- */


int main( int argc, char *argv[] ) {

        std::string path( argv[ 1 ] );
    WavFileForIO *myWav = new WavFileForIO( path );
    //myWav->read();    char *summary = myWav->getSummary();    printf("Summary:\n%s", summary );


    PaStreamParameters inputParameters, outputParameters;
    PaStream *stream;
    PaError err;
    SAMPLE *recordedSamples;
    int i;
    int totalFrames;
    int numSamples;
    int numBytes;
    SAMPLE max, average, val;

    //vector<int> dsin;
    vector<double> dsin;
    vector<double> dfourier;
    unsigned int n;
    
    printf("patest_read_record.c\n"); fflush(stdout);

    totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */
    numSamples = totalFrames * NUM_CHANNELS;

    numBytes = numSamples * sizeof(SAMPLE);
    recordedSamples = (SAMPLE *) malloc( numBytes );
    if( recordedSamples == NULL ){
        printf("Could not allocate record array.\n");
        exit(1);
    }
    for( i=0; i<numSamples; i++ ) recordedSamples[i] = 0;

    err = Pa_Initialize();
    if( err != paNoError ) goto error;

    inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
    inputParameters.channelCount = NUM_CHANNELS;
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;
    inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
    inputParameters.hostApiSpecificStreamInfo = NULL;

    /* Record some audio. -------------------------------------------- */
    err = Pa_OpenStream(
        &stream,
        &inputParameters,
        NULL,                  /* &outputParameters, */
        SAMPLE_RATE,
        FRAMES_PER_BUFFER,
        paClipOff,      /* we won't output out of range samples so don't bother clipping them */
        NULL, /* no callback, use blocking API */
        NULL ); /* no callback, so no callback userData */
    if( err != paNoError ) goto error;

    err = Pa_StartStream( stream );
    if( err != paNoError ) goto error;
    printf("Now recording!!\n"); fflush(stdout);

    err = Pa_ReadStream( stream, recordedSamples, totalFrames );
    if( err != paNoError ) goto error;
    
    err = Pa_CloseStream( stream );
    if( err != paNoError ) goto error;

    /* Measure maximum peak amplitude. */
    max = 0;
    average = 0;
    for( i=0; i<numSamples; i++ ) {
        val = recordedSamples[i];
        if( val < 0 ) val = -val; /* ABS */
        if( val > max )
        {
        max = val;
        }
        average += val;
    }

    average = average / numSamples;

    printf("Sample max amplitude = "PRINTF_S_FORMAT"\n", max );
    printf("Sample average = "PRINTF_S_FORMAT"\n", average );

    FILE  *fid;
    fid = fopen("out/recorded.raw", "wb");
    if( fid == NULL ) {
        printf("Could not open file.");
    } else {
        fwrite( recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
        fclose( fid );
        printf("Wrote data to 'recorded.raw'\n");
    }

    /* сохраняем в wav */
    
    myWav->myData = new char[ numSamples ];
    myWav->myDataSize = numSamples;
    myWav->myChunkSize = 36 + myWav->myDataSize;

    for( i = 0; i < numSamples; i++ ) {
        myWav->myData[ i ] = ( ( char )( ( recordedSamples[ i ] ) >> 8 ) );
    }
    myWav->setPath( "out/testout.wav" );
    myWav->save();
    
    free( recordedSamples );

    Pa_Terminate();
    return 0;

    error:
    Pa_Terminate();
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
    fprintf( stderr, "Error number: %d\n", err );
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    return -1;
    
}


Это сообщение отредактировал(а) Proger10 - 9.12.2009, 22:22
PM MAIL   Вверх
Alexeis
Дата 9.12.2009, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 4
Всего: 459



Proger10, может звук был исходно 8ми битным, тогда получилось прореживание и соответственно 2х кратное увеличение частоты, либо частота дискретизации при записи была ниже, чем устанавливается при проигрывании.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Proger10
Дата 9.12.2009, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Да тут видите всё явно устанавливается.. звук 16-бит:
#elif 1
#define PA_SAMPLE_TYPE  paInt16
...
при записи в файл 16 бит:
            mySubChunk1Size = 16;
            myFormat = 1;
            myChannels = 1;
            mySampleRate = 11025;
            myByteRate = 22050;
            myBlockAlign = 2;
            myBitsPerSample = 16;

в принципе тут навряд ли можно допустить ошибку в частотах...
PM MAIL   Вверх
586
Дата 10.12.2009, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 8
Всего: 146



Цитата(Proger10 @  9.12.2009,  23:04 Найти цитируемый пост)
при записи в файл 16 бит:
            mySubChunk1Size = 16;
            myFormat = 1;
            myChannels = 1;
            mySampleRate = 11025;
            myByteRate = 22050;
            myBlockAlign = 2;
            myBitsPerSample = 16;

При сохранении в 8 бит, параметру myByteRate не присваивается значение 11025.
PM   Вверх
Proger10
Дата 10.12.2009, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(586 @ 10.12.2009,  12:15)
Цитата(Proger10 @  9.12.2009,  23:04 Найти цитируемый пост)
при записи в файл 16 бит:
            mySubChunk1Size = 16;
            myFormat = 1;
            myChannels = 1;
            mySampleRate = 11025;
            myByteRate = 22050;
            myBlockAlign = 2;
            myBitsPerSample = 16;

При сохранении в 8 бит, параметру myByteRate не присваивается значение 11025.

Не очень понял.. У меня не присваивается? Или вообще по теории присваивать не нужно это число? Я вроде с 16 битами работаю...

Добавлено через 1 минуту и 48 секунд
Вроде Вы выделили 22050, а сказали что не присваивается 11025.. что-то совсем не понял по контексту Вашего ответа что к чему.. smile
PM MAIL   Вверх
586
Дата 10.12.2009, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 8
Всего: 146



Цитата(Proger10 @  10.12.2009,  15:14 Найти цитируемый пост)
Я вроде с 16 битами работаю...

Там же идёт конвертирование из 16 бит в 8 бит. Что же получается - Вы пишете 8-битный wav-файл с заголовком, как для 16-битного wav?
Откуда взялось число myByteRate = 22050.
Должно быть myByteRate равен 11025.
myBitsPerSample равен 8
myBlockAlign равен 1

PM   Вверх
Proger10
Дата 10.12.2009, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



>>myBitsPerSample равен 8
при 16-битном звуке? 

Ок, сейчас попробую то поправить.. Я это число увидел из 16 битного файла, который мне экспортировала Audacity.

Добавлено через 9 минут и 10 секунд
Неа, никаких различий нет с внесёнными измнениями :(
Код


            mySubChunk1Size = 16;
            myFormat = 1;
            myChannels = 1;
            mySampleRate = 11025;
            myByteRate = 11025;
            myBlockAlign = 1;
            myBitsPerSample = 16;


Добавлено через 11 минут и 15 секунд
Кстати, а почему BlockAlign должен быть равен одному? Получается двум..
BlockAlign       == NumChannels * BitsPerSample/8

У меня каналов: 1, бит: 16, получается: 1 * 16/8 = 2

Добавлено через 12 минут и 56 секунд
Мне нужно записывать 16 битный звук, а не 8-битный...
PM MAIL   Вверх
Proger10
Дата 10.12.2009, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Аналогично и с ByteRate:
ByteRate         == SampleRate * NumChannels * BitsPerSample/8
ByteRate         == 11025 * 1 * 16/8 == 22050
PM MAIL   Вверх
586
Дата 10.12.2009, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 8
Всего: 146



Цитата(Proger10 @  9.12.2009,  22:22 Найти цитируемый пост)
    for( i = 0; i < numSamples; i++ ) {
        myWav->myData[ i ] = ( ( char )( ( recordedSamples[ i ] ) >> 8 ) );
    }
    myWav->setPath( "out/testout.wav" );
    myWav->save();

Здесь какой файл сохраняется? 8-битный или 16 битный?
PM   Вверх
Proger10
Дата 10.12.2009, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



А смещение случаем не на 16 нужно делать для 16битного звука?
myWav->myData[ i ] = ( ( char )( ( recordedSamples[ i ] ) >> 16 ) );

тем не менее не фурычит
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0665 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.