Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Mono -> Stereo Wav, Mono в Stereo 
:(
    Опции темы
Domen
  Дата 15.3.2011, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте Эксперты!) 
Требуется из Моно Wav-файла сделать стерео.
Как удвоить каждый Чанк, на сколько я понимаю с созданием нового делать невозможно?
А без создания тоже не работает верно. На обычном массиве это так, работает:
Код

 for(int i=9; i>=0; i--)
     {a[2*i]=a[i];}
 for(int i=0;i<10; i++)
  a[2*i+1]=a[2*i];
   for (int i=0; i<100; i++)
   cout<<a[i]<<endl;


Как сделать размер результирующего больше исходного чтоб поместить Отсчеты? 
Весь код в стадии:
Код

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include <windows.h>    /* в этом файле определены типы BYTE, WORD, DWORD,... */
                        /* и тип WAVE_FORMAT_PCM */
/*  коды завершения функции get_wav_header()  */

using namespace std;

#define NO_ERRORS            0
#define ILLEGAL_HEADER        1
#define ILLEGAL_FORMAT        2
#define READ_ERROR            3
#define MAXHDRLEN            1000

// определение типа WAVE_HEADER
// Это простейший заголовок, реально может быть более сложным, но мы учтем
// это при чтении и проверке заголовка
typedef struct
{
    /*  подзаголовок RIFF  */
    BYTE    riff[4];        // тут должны бфть буквы RIFF
    DWORD    riffsize;        // размер файла - 8
    
    /* подзаголовок FORMAT, описывает формат WAV файла  */
    char    wavefmt[8];            // тут должны быть буквы "WAVEfmt "
    DWORD    fmtsize;            // размер подзаголовка FORMAT - может быть только 16 или 18
                                // для минимального заголовка WAV достаточно значения 16
    WORD    wFormatTag;            // формат файла , нас интересует только WAVE_FORMAT_PCM ( == 1 )
    WORD    nChannels;            // число каналов ( 1 или 2 )
    DWORD    nSamplesPerSec;        // число отсчетов в секунду ( 8000, 11025, 22050 или 44100 )
    DWORD    nAvgBytesPerSec;    // число байт в секунду. 
    WORD    nBlockAlign;        // выравнивание блока данных
    SHORT    wBitsPerSample;        // число бит на отсчет ( 8 или 16 )

    /*  DATA chunk  ( chunk == кусок ) */
    BYTE    data[4];            // тут должны быть буквы "data"
    DWORD    datasize;            // размер данных в байтах 
                                /* далее в файле идут данные, размер которых == datasize  */
    /*  к сожалению, могут встречаться и другие чанки, не только data
        во многих файлах перед data чанком идет fact чанк, который содержит информацию о кодере и дате
        создания файла. Такие куски нам надо будет пропустить */
} WAVE_HEADER, *LPWAVE_HEADER;

// определение тип DATA_CHUNK
typedef struct
{
    BYTE    data[4];
    DWORD    datasize;

} DATA_CHUNK;

WAVE_HEADER wav_hdr;


/*  чтение заголовка WAV файла  */
DWORD get_wav_header( FILE *file, WAVE_HEADER *whd )
{
    // читает WAVE_HEADER, контролирует его корректность и возвращает код ошибки, 
    // или 0, если все в порядке
    char buf[4];
    DWORD i;
    DWORD j;
    DWORD bytecnt = 0;        // счетчик прочитанных из файла байт
    DATA_CHUNK dat_hdr;        // 

    // читаем часть заголовка, без дополнительних байтов в формате и без DATA_CHUNK
    if( fread( (char *)whd, sizeof(WAVE_HEADER) - sizeof(DATA_CHUNK), 1, file )!= 1)
        return READ_ERROR;    // выход по ошибке чтения

    if( strncmp( whd->wavefmt, "WAVEfmt ", 8) != 0 )
        return ILLEGAL_HEADER;  // поле wavefmt не содержит символов "WAVEfmt "

    if( whd->wFormatTag != WAVE_FORMAT_PCM )
        return ILLEGAL_FORMAT;    // формат файла - не WAVE_FORMAT_PCM, это может быть один из сжатых
                                // файлов - MP3 , ADPCM , ...

    if (whd->fmtsize > 16)    // у прочитанной части заголовка более длинный формат,
    {                            // надо прочитать лишние байты, они нас не интересуют
        i = (SHORT)whd->fmtsize;
        while (i > 16)
        {
            j = min(sizeof( buf ), i - 16);
            if( fread( buf, j, 1, file )!= 1)
                return READ_ERROR;
            i -= j;
        }
        whd->fmtsize = 16L;        // наш WAVEFORMAT будет иметь длину 16 байт
    }
    // ищем "data" чанк
    while( bytecnt <= MAXHDRLEN )    // искать до бесконечности мы не будем
    {
        /*  прочитать заголовок очередного chunk'a  */
        if( fread( (char *)&dat_hdr, sizeof( DATA_CHUNK ), 1, file )!= 1)
            return READ_ERROR;        // ошибка чтения
        i = dat_hdr.datasize;        // размер

        /* проверим, является ли прочитанных подзаголовок началом data-чанка*/
        if( strncmp( (char*)&dat_hdr.data, "data", 4 ) == 0 )
        {      // нашли data chunk
            memcpy( (char*)&whd->data, "data", 4 );        // копируем символы "data" в наш header
            whd->datasize = dat_hdr.datasize;            // копируем размер данных
            return NO_ERRORS;                                // нормальный выход, header прочитан
        }
        // это не "data" chunk, пропускаем
        bytecnt += i;    // считаем байты до DATA_CHUNK
        while ( i > 0 )    
        {
            j = min(sizeof( buf ), i );
            if( fread( buf, j, 1, file )!= 1)
                return READ_ERROR;
            i -= j;
        }

    }
    return ILLEGAL_HEADER;    // искали-искали, и не нашли
}

/*  Написать программу, уменьшающую амплитуду файла в 2 раза, если максимальная амплитуда > 30000, и в 1.5 раза
  в противном случае
    Предполагается, что файл содержит 16-битные отсчеты, файл - моно ( 1 канал )  
  */
void main( int argc, char *argv[] )
{
    FILE *fin, *fout;
    DWORD nsamples;
    short *nsamples2;
    DWORD datasize;
    WORD nChannels;
    short *samples;
    WORD  maxval;
    DWORD i;
    DWORD j;
    double coeff;
    DWORD RetCode;
    int Channels = 2;    // число каналов
    int Maxnsaples;

    if( argc < 3 )
    {
        printf("Run: wav_exm.exe <src_wav> <dst_wav>\n");
        exit(1);
    }

    /*  открыть исходный файл */
    if( (fin = fopen(argv[1],"rb"))==NULL )
    {
        printf("File %s open error\n", argv[1] );
        exit(1);
    }

    /* открыть результирующий файл */
    if( (fout=fopen(argv[2],"wb"))==NULL)
    {
        printf("File %s open error\n", argv[2] );
        exit(1);
    }

    // читаем заголовок входного файла и определяем количество данных
    RetCode = get_wav_header( fin, &wav_hdr );
    /* анализируем код возврата */
    switch( RetCode )
    {
    case READ_ERROR:
        printf("Source file read error\n");
        exit(1);
    case ILLEGAL_FORMAT:
        printf("Illegal header format\n");
        exit(1);
    case ILLEGAL_HEADER:
        printf("Illegal hrader\n");
        exit(1);
    }
    //  приходим, если RetCode == NO_ERRORS
    datasize = wav_hdr.datasize;    //    размер данных в байтах
    nsamples = datasize /2;            //  число отсчетов ( для 16-битных отсчетов )
    wav_hdr.nChannels=2;
    /*  закажем память для данных */
    samples = (short*)malloc( datasize );
    nsamples2= (short*)malloc( datasize*2 );
    if( samples == NULL )
    {
        printf("Allocation error\n");
        exit(1);
    }
    // читаем весь файл в память
    if( fread( samples, datasize, 1, fin ) != 1 )
    {
        printf("read file error\n");
        exit(1);
    }
    nChannels=2;
    // нормализация
    for(i=0;i<nsamples;i++)
    {
        nsamples2[2*i] = samples[i];
        nsamples2[2*i+i] = samples[i];
    }

    // записать выходной файл
    samples = (short*)malloc( datasize );
    nsamples = datasize /2;    
    /* корректируем riffsize, т.к. он мог измениться, если в исходном файле был более сложный header */
    wav_hdr.riffsize = wav_hdr.datasize + 36;
    /*  сначала записываем заголовок */
    fwrite( &wav_hdr, sizeof( wav_hdr), 1, fout );
    fwrite( samples, (datasize), 1, fout );

    /* закрываем файлы */
    fclose( fin);
    fclose(fout);
    printf("Done.\n");
}
 
PM MAIL   Вверх
Estranged
Дата 15.3.2011, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Насколько я помню отличие моно от стерео, то это блоки данных по SHORT    wBitsPerSample;        // число бит на отсчет ( 8 или 16 ) в моно идут сплошным потоком блоке данных, а в стерео чередуются правый/левый. Поэтому есть мнение, что надо каждый чанк писать по два раза в новый файл, не забыть про новый заголовок.

Дома есть умная книжка, где можно почерпнуть инфу.
PM MAIL   Вверх
Domen
Дата 15.3.2011, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Это и пытаемся сделать) Вот так переделал, но всё равно что-то не то. smile 
Код

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include <windows.h>    /* в этом файле определены типы BYTE, WORD, DWORD,... */
                        /* и тип WAVE_FORMAT_PCM */
/*  коды завершения функции get_wav_header()  */

using namespace std;

#define NO_ERRORS            0
#define ILLEGAL_HEADER        1
#define ILLEGAL_FORMAT        2
#define READ_ERROR            3
#define MAXHDRLEN            1000

// определение типа WAVE_HEADER
// Это простейший заголовок, реально может быть более сложным, но мы учтем
// это при чтении и проверке заголовка
typedef struct
{
    /*  подзаголовок RIFF  */
    BYTE    riff[4];        // тут должны бфть буквы RIFF
    DWORD    riffsize;        // размер файла - 8
    
    /* подзаголовок FORMAT, описывает формат WAV файла  */
    char    wavefmt[8];            // тут должны быть буквы "WAVEfmt "
    DWORD    fmtsize;            // размер подзаголовка FORMAT - может быть только 16 или 18
                                // для минимального заголовка WAV достаточно значения 16
    WORD    wFormatTag;            // формат файла , нас интересует только WAVE_FORMAT_PCM ( == 1 )
    WORD    nChannels;            // число каналов ( 1 или 2 )
    DWORD    nSamplesPerSec;        // число отсчетов в секунду ( 8000, 11025, 22050 или 44100 )
    DWORD    nAvgBytesPerSec;    // число байт в секунду. 
    WORD    nBlockAlign;        // выравнивание блока данных
    SHORT    wBitsPerSample;        // число бит на отсчет ( 8 или 16 )

    /*  DATA chunk  ( chunk == кусок ) */
    BYTE    data[4];            // тут должны быть буквы "data"
    DWORD    datasize;            // размер данных в байтах 
                                /* далее в файле идут данные, размер которых == datasize  */
    /*  к сожалению, могут встречаться и другие чанки, не только data
        во многих файлах перед data чанком идет fact чанк, который содержит информацию о кодере и дате
        создания файла. Такие куски нам надо будет пропустить */
} WAVE_HEADER, *LPWAVE_HEADER;

// определение тип DATA_CHUNK
typedef struct
{
    BYTE    data[4];
    DWORD    datasize;

} DATA_CHUNK;

WAVE_HEADER whd;
DATA_CHUNK dat_hdr;


/*  чтение заголовка WAV файла  */
DWORD get_wav_header( FILE *file, WAVE_HEADER *whd )
{
    // читает WAVE_HEADER, контролирует его корректность и возвращает код ошибки, 
    // или 0, если все в порядке
    char buf[4];
    DWORD i;
    DWORD j;
    DWORD bytecnt = 0;        // счетчик прочитанных из файла байт

    // читаем часть заголовка, без дополнительних байтов в формате и без DATA_CHUNK
    if( fread( (char *)whd, sizeof(WAVE_HEADER) - sizeof(DATA_CHUNK), 1, file )!= 1)
        return READ_ERROR;    // выход по ошибке чтения

    if( strncmp( whd->wavefmt, "WAVEfmt ", 8) != 0 )
        return ILLEGAL_HEADER;  // поле wavefmt не содержит символов "WAVEfmt "

    if( whd->wFormatTag != WAVE_FORMAT_PCM )
        return ILLEGAL_FORMAT;    // формат файла - не WAVE_FORMAT_PCM, это может быть один из сжатых
                                // файлов - MP3 , ADPCM , ...

    if (whd->fmtsize > 16)    // у прочитанной части заголовка более длинный формат,
    {                            // надо прочитать лишние байты, они нас не интересуют
        i = (SHORT)whd->fmtsize;
        while (i > 16)
        {
            j = min(sizeof( buf ), i - 16);
            if( fread( buf, j, 1, file )!= 1)
                return READ_ERROR;
            i -= j;
        }
        whd->fmtsize = 16L;        // наш WAVEFORMAT будет иметь длину 16 байт
    }
    // ищем "data" чанк
    while( bytecnt <= MAXHDRLEN )    // искать до бесконечности мы не будем
    {
        /*  прочитать заголовок очередного chunk'a  */
        if( fread( (char *)&dat_hdr, sizeof( DATA_CHUNK ), 1, file )!= 1)
            return READ_ERROR;        // ошибка чтения
        i = dat_hdr.datasize;        // размер

        /* проверим, является ли прочитанных подзаголовок началом data-чанка*/
        if( strncmp( (char*)&dat_hdr.data, "data", 4 ) == 0 )
        {      // нашли data chunk
            memcpy( (char*)&whd->data, "data", 4 );        // копируем символы "data" в наш header
            whd->datasize = dat_hdr.datasize;            // копируем размер данных
            return NO_ERRORS;                                // нормальный выход, header прочитан
        }
        // это не "data" chunk, пропускаем
        bytecnt += i;    // считаем байты до DATA_CHUNK
        while ( i > 0 )    
        {
            j = min(sizeof( buf ), i );
            if( fread( buf, j, 1, file )!= 1)
                return READ_ERROR;
            i -= j;
        }

    }
    return ILLEGAL_HEADER;    // искали-искали, и не нашли
}

void make_new(FILE *file, short *samples)
{
    short *samples2;
    DWORD size2;//новое количество сэмплов
    short i,y;

    whd.nChannels=2;
    whd.nAvgBytesPerSec=(whd.nChannels*whd.nSamplesPerSec*whd.wBitsPerSample/8);//это формула
    whd.nBlockAlign=(whd.nChannels*whd.wBitsPerSample/8);//и это формула
    

    size2=dat_hdr.datasize*2;//количество сэмлов увеличится в 2 раза

    samples2=new short [size2];
    for(i=0;i<size2;samples2[i++]=0);//новый массив проинициализируем 0;
       
        for(i=0;i<dat_hdr.datasize; i++)        
        {
            samples2[i]=samples[i];
            samples2[2*i+i]=samples[i];

        }
    
    dat_hdr.datasize=size2;
    whd.riffsize=whd.riffsize-size2;//размер файла  
    fwrite(&whd,sizeof(whd),1,file);//запишим все  в новый файл
    fwrite(&dat_hdr,sizeof(dat_hdr),1,file);
    fwrite(samples2,size2,1,file);
    
}

/*  Программа, формирующая по исходному моно WAV файлу
   новый стерео WAV файл  
  */
void main( int argc, char *argv[] )
{
    FILE *fin, *fout;
    DWORD datasize;
    short *samples;
    DWORD i;
    DWORD RetCode;
    int Channels = 2;    // число каналов

    if( argc != 3 )
    {
        printf("Run: wav_exm.exe <src_wav> <dst_wav>\n");
        exit(1);
    }

    /*  открыть исходный файл */
    if( (fin = fopen(argv[1],"rb"))==NULL )
    {
        printf("File %s open error\n", argv[1] );
        exit(1);
    }


    // читаем заголовок входного файла и определяем количество данных
    RetCode = get_wav_header( fin, &whd );
    /* анализируем код возврата */
    switch( RetCode )
    {
    case READ_ERROR:
        printf("Source file read error\n");
        exit(1);
    case ILLEGAL_FORMAT:
        printf("Illegal header format\n");
        exit(1);
    case ILLEGAL_HEADER:
        printf("Illegal hrader\n");
        exit(1);
    }
    //  приходим, если RetCode == NO_ERRORS
    datasize = whd.datasize;    //    размер данных в байтах
    /*  закажем память для данных */
    //samples = (short*)malloc( datasize );
    samples=new short [dat_hdr.datasize];

    if( samples == NULL )
    {
        printf("Allocation error\n");
        exit(1);
    }
    // читаем весь файл в память
    if( fread( samples, datasize, 1, fin ) != 1 )
    {
        printf("read file error\n");
        exit(1);
    }

        /* открыть результирующий файл */
    if( (fout=fopen(argv[2],"wb"))==NULL)
    {
        printf("File %s open error\n", argv[2] );
        exit(1);
    }

    // записать выходной файл
    make_new(fout,samples);
    /* закрываем файлы */
    fclose( fin);
    fclose(fout);
    printf("Done.\n");
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

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


 




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


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

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