void SEISM_SIGNAL::SaveToWav(CArray<double,double> *data_array)
{
CArray <int,int>WAVarray;
WAVEFORMATEX m_pcm;
double max=0;
//Init PCM
m_pcm.nChannels=2;
m_pcm.nSamplesPerSec=freq;
m_pcm.wBitsPerSample=16;
m_pcm.wFormatTag=WAVE_FORMAT_PCM;
m_pcm.nBlockAlign = m_pcm.nChannels * m_pcm.wBitsPerSample/8;
m_pcm.nAvgBytesPerSec = m_pcm.nSamplesPerSec * m_pcm.nChannels * m_pcm.wBitsPerSample/8;
//Приводим сигнал к формату 16бит
for (int i=0; i<data_array->GetSize();i++)
{
double temp=data_array->GetAt(i);
if (temp > max) max=temp;
}
double coeff=16383/max; //не нормализуем по максимуму, чтобы исключить переполнение
for (i=0; i<data_array->GetSize();i++)
{
double temp=data_array->GetAt(i)*coeff;
int val=(int)temp;
WAVarray.Add(temp);
}
CFile f("1.wav", CFile::modeCreate | CFile::modeWrite);
f.Write("RIFF", 4) ;
DWORD dwFileSize = WAVarray.GetSize() * m_pcm.nBlockAlign + 36 ;
f.Write(&dwFileSize, sizeof(dwFileSize)) ;
f.Write("WAVEfmt ", 8) ;
DWORD dwFmtSize = 16;
f.Write(&dwFmtSize, sizeof(dwFmtSize)) ;
f.Write(&m_pcm.wFormatTag, sizeof(m_pcm.wFormatTag)) ;
f.Write(&m_pcm.nChannels, sizeof(m_pcm.nChannels)) ;
f.Write(&m_pcm.nSamplesPerSec, sizeof(m_pcm.nSamplesPerSec)) ;
f.Write(&m_pcm.nAvgBytesPerSec, sizeof(m_pcm.nAvgBytesPerSec)) ;
f.Write(&m_pcm.nBlockAlign, sizeof(m_pcm.nBlockAlign)) ;
f.Write(&m_pcm.wBitsPerSample, sizeof(m_pcm.wBitsPerSample)) ;
f.Write("data", 4) ;
DWORD dwNum = WAVarray.GetSize() * m_pcm.nBlockAlign;
f.Write(&dwNum, sizeof(dwNum)) ;
f.Write(WAVarray.GetData(),dwNum);
f.Close();
}
Сборка WAV-файла
В функцию засылаются внешние данные, пережевываются к формату 16 бит и выплёвываются в wav-файл
Код:
Так работает более менее корректно: в левом канале данные, правый пустой (все значения - нулевые).
Фишка в том, что если собирать моно-сигнал:
Код:
m_pcm.nChannels=1;
То нули из правого канала перескакивают в левый и получается примерно следующая картина: отсчет, ноль, отсчет, ноль и т.д.
В чём тут может быть фишка?
В моно выборки идут так: выборка1, выборка2, выборка3, ..., выборкаN
В стерео: выборкаRight1, выборкаLeft1, выборкаRight2, выборкаLeft2, выборкаRight3, выборкаLeft3, ..., выборкаRightN, выборкаLeftN.
В предоставленном коде я не нашел пересчета данных в зависимости от количества каналов.
Т.е. на выходе получаем: выборка1 (Right1), выборка2 (Left1), выборка3(Right2), выборка4(Left2) и т.д.
Может я перепутал какая выборка идет первой в стерео файле - левая или правая, но суть от этого не меняется.
Нужно сначала преобразовать данные от стерео звука к моно. Самое простое - это выкинуть один из каналов, либо смикшировать 2 канала (среднее из двух выборок - левой и правой). При микшировании следует помнить, что если работаем с реальным аудио сигналом, то если он идет в 2х каналах в противофазе, то в результате микширования получим ноль :)
P.S.
Размер одной выборки в данном случае 2 байта (16 бит). Надо помнить, что если будем менять формат с 16 бит на 8 бит, соответственно надо перелопатить и буфер данных
Один за одним. Последовательно.
В стерео первой идёт "левая" выборка. Но это действительно, не суть важно.
На входе НЕТ файла, ни стерео ни моно. Он СОБИРАЕТСЯ из отсчетов. При этом корректно работает только стерео сборка.
Проще говоря этот одномерный массив трактуется по разному при сборке в стерео и моно WAV файлов.
В случае стерео массив данных состоит из структур
struct STEREO_SAMPLE
{
short leftSample;
short rightSample;
};
В случае моно -
struct MONO_SAMPLE
{
short monoSample;
};
каждая структура (элемент массива структур) - это одна выборка.
Если на входе одномерный массив, с выборками для 2х каналов (левый/правый), перед тем как писать в файл нужно этот массив преобразовать в моно.
Может я не правильно понял суть проблемы? Чего собственно нужно добиться?
Если утрировать до "на пальцах", то
есть массив {1,2,3,4,5,6,7} (WAVarray)
физически он представляет собой целочисленные отсчеты, полученные от сейсмического датчика
Этот массив надо представить в виде моно wav-файла.
а в чем проблема?
WAVarray надо определять как
CArray <short,short>WAVarray;
т.е. длина элемента массива (в байтах) должна быть равна битности WAV файла, в данном случае 16 бит
Жара в офисе неблагоприятно сказывается на деятельность серого вещества.
Br@in RIPper, Спасибо!
Тему можно считать закрытой