Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Запись данных в wav файл


Автор: shell14 20.5.2006, 19:25
Подскажите как записать данные в wav файл? Я записал полностью структуру заголовка файла, все нормально. Интересуют вопрос именно запись данных в файл.
Особой сложности не возникает, потому что файл нужен mono, не сжатый (PCM), 44100 Hz, и 16 bit per sample. т.е. как я понимаю сами данные должны храниться в массиве 2байтовых слов, (например short подойдет?).
вот, теперь отдельно вопросы:
как правильно организовать цикл записи данных, т.е. как сделать выборку? например любой сигнал в форме sin, если я хочу записать файл ну скажем длительностью 30 секунд?    


typedef struct waveformat_tag { 
    WORD wFormatTag; // тип формата 
    WORD nChannels; // количество каналов (моно или стeрео) 
    DWORD nSamplesPerSec; // частота дискретизации 
    DWORD nAvgBytesPerSec; // скорость потока данных 
    WORD nBlockAlign; // выравнивание блока данных 
} WAVEFORMAT; 

Автор: GremlinProg 20.5.2006, 23:25
Если тебе нужен корректный WAV, который впоследствии можно было послушать, то разбирай структуру WAV файла. Общая структура RIFF файлов подробно, с примерами, описана в MSDN'е. Это набор функций mmio-. По вавам - не помню, врать не буду. WAV - эточастный случай RIFF. Обратись в раздел форума WinAPI, а лучше воспользуйся поиском. 

Автор: shell14 21.5.2006, 01:46
GremlinProg, спасибо конечно, но с форматом я вроде как раз разобрался возникает именно проблема с данными... файл получаеться занимает n-ое колличество килобайт, но при этом winamp п оказывает 0 секунд 

Автор: shell14 21.5.2006, 02:43
Хорошо, народ можете подсказать какой сигнал задать чтоб хоть какой-нибудь нормальный звук получился? ну например какие параметры для синуса? 

Автор: GremlinProg 21.5.2006, 11:46
Цитата

но при этом winamp п оказывает 0 секунд  

Chunk "data" значит имеет нулевую длину.

А сформировать любой сигнал - просто: заполни массив данных хотя бы так:
Код

    for(size_t i = 100;i--;)
        data[i]    = 32768;

Это будет гул на частоте дискретизации максимальной громкости
Код

    for(size_t i = 100;i--;)
        if(!(i%10))
            data[i]    = 0;
        else
            data[i]    = 32768;

Это еще простенький примерчик, разницу сам услышишь.
в обоих примерах используется 16 битное ИКМ с одним каналом на 100 семплов 

Автор: shell14 21.5.2006, 13:50
GremlinProg, спасибо, все заработало!!! у меня действительно был баг с записью размера!
только теперь остался один вопрос, ведь чем больше будет время, тем соответсвенно получаеться больше размер данных. Но ведь я не могу выделить памать под бесконечный объем. 
я имею ввиду например, что для длительности 40 секунд мне нужно 
Код

short DATA[1631700];
 элементов... а что делать если мне нужен сигнал боьшей длительности?

Просто я организовал выборку данных в массив циклом по времени.
Код


count = double(1.0/(write->head.nSamplesPerSec));//write->head.nSamplesPerSec = 44100 частота    

long size = time/count;//определяю размер данных

short DATA[size];

double j = count;
     while (count < time)
        
     {
        
    
      d = 100*sin(2 * pi * (5 * count) * (500 * count));

        count += j;    
      
        DATA[i] = d;
        i++;

    
    }
 

Автор: regis 22.5.2006, 10:59
Цитата(shell14 @ 21.5.2006,  13:50)
GremlinProg, спасибо, все заработало!!! у меня действительно был баг с записью размера!
только теперь остался один вопрос, ведь чем больше будет время, тем соответсвенно получаеться больше размер данных. Но ведь я не могу выделить памать под бесконечный объем. 
я имею ввиду например, что для длительности 40 секунд мне нужно 
Код

short DATA[1631700];
 элементов... а что делать если мне нужен сигнал боьшей длительности?
[/code]

Буферизовать данные в памяти и время от времени дописывать в файл, естественно. 

Автор: shell14 24.5.2006, 23:36
ааа, точно, спасибо 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)