Создание файла .wav из данных PCM - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь прочитать данные из SPH0645LM4H-B https://www.knowles.com/docs/default-source/model-downloads/sph0645lm4h-b-datasheet-rev-c.pdf?sfvrsn=4 и преобразовать их в формат .wav, чтобы я мог проверить, правильно ли работает мой датчик.До сих пор мне удалось подключить датчик и прочитать образцы данных с помощью передачи i2s-dma.

Кроме того, я обнаружил, что большинство основных форматов компьютерных звуковых файлов состоят из заголовка (содержащего длину и т. Д.) с последующим 16-разрядным PCM с двумя дополнениями https://www.dsprelated.com/freebooks/mdft/Number_Systems_Digital_Audio.html

Для преобразования данных PCM в волновой формат я сослался на преобразование PCM в файл wav

Теперь формат данных датчика: I2S, 24-битный, комплимент 2, MSB в первую очередь.Точность данных составляет 18 бит;неиспользуемые биты нули.Я преобразовал данные датчика в 32-разрядный (MSB - знаковый бит)

Я использовал код из следующей ссылки (и ссылки, упомянутые в нем), чтобы создать файл .wav: - Добавление .pcm аудио необработанных данных в wav (в C)

//. Данные заголовка файла wav

struct wavfile
{
char            id[4];          // should always contain "RIFF"
int             totallength;    // total file length minus 8
char            wavefmt[8];     // should be "WAVEfmt "
int             format;         // 16 for PCM format
short           pcm;            // WAVE_FORMAT_IEEE_FLOAT (3).
short           channels;       // channels
int             frequency;      // sampling frequency, 16000 in this case
int             bytes_per_second;
short           bytes_by_capture;
short           bits_per_sample;
char            data[4];        // should always contain "data"
int             bytes_in_data;
};

// Запись заголовка в выходной файл .wav

void write_wav_header(char* name, int samples, int channels)
{
struct wavfile filler;
FILE *pFile;
strcpy(filler.id, "RIFF");
filler.totallength = (samples * channels) + sizeof(struct wavfile) - 8;
strcpy(filler.wavefmt, "WAVEfmt ");
filler.format = 16;
filler.pcm = 3; // WAVE_FORMAT_IEEE_FLOAT (3).
filler.channels = channels;
filler.frequency = 32000;
filler.bits_per_sample = 32;
filler.bytes_per_second = filler.channels * filler.frequency * filler.bits_per_sample/8;
filler.bytes_by_capture = filler.channels*filler.bits_per_sample/8;
filler.bytes_in_data = samples * filler.channels * filler.bits_per_sample/8;
strcpy(filler.data, "data");
pFile = fopen(name, "wb");
fwrite(&filler, 1, sizeof(filler), pFile);
fclose(pFile);
}

// Добавление данных аудиодатчика к этому WAV-файлу

void write_pcm_data_to_file(char* inFile, char* outFile)
{
char buffer[SAMPLE_SIZE];
size_t n;
FILE *fin,*fout;
fin = fopen(inFile,"r");
fout = fopen(outFile,"a");
while((n = fread(buffer, 1, sizeof(buffer), fin)) > 0)
{
    if(n != fwrite(buffer, 1, n, fout))
    {
        perror("fwrite");
        exit(1);
    }
}
fclose(fin);
fclose(fout);
}

Вот так выглядит результирующий WAV-файл в шестнадцатеричном редакторе: - .wav файл в шестнадцатеричном форматередактор Я вижу, что значения заголовка wav установлены правильно, а затем мои данные PCM из Audio Sensor.

Однако при воспроизведении файла .wav я не могу воспроизвести входной звук,Вместо этого я слышу постоянный тон.Я попытался изменить входной звук (проиграл различную музыку, песни), но полученный файл .wav воспроизводит один и тот же постоянный тон.

Чтобы воссоздать входную музыку, воспроизводимую на микрофон, в файл wav, какие модификациимне делать?

Заранее спасибо.

Редактировать: -

Согласно ответу 42LeapsOfFaith, преобразоватьмои образцы в шестнадцатеричное, я использовал следующий код: -

hexValue = strtoll(sample, NULL, 16);

Я преобразовал каждое значение в буфере, а затем записал его в мой файл .wav.Теперь мой файл .wav выглядит как измененный файл .wav в шестнадцатеричном редакторе

Однако даже этот файл wav не воспроизводит звук.Любые дальнейшие предложения по воссозданию входной музыки, воспроизводимой на микрофон, в файл wav?

Помощь очень ценится

1 Ответ

0 голосов
/ 22 ноября 2018

Для начала, вы сохраняете данные PCM в файле как ascii-hex.Надеюсь, это поможет.

Это «хак», который вы можете использовать ...

char c[2];
while((n = fread(&c[0], 2, 1, fin)) > 0)
 { 
    if (c[0] > 0x39) c[0] -= 7;
    c[0] &= 0x0F;
    if (c[1] > 0x39) c[1] -= 7;
    c[1] &= 0x0F;
    c[1] |= c[0] << 4;
    if(1 != fwrite(&c[1], 1, 1, fout))
...