簡體   English   中英

寫入 WAV 文件 C++

[英]Writing to WAV file C++

我有一個關於數字信號處理課程的WAV文件和FIR濾波器的作業。

我的程序必須讀取一個WAV文件,對數據應用過濾器並將輸出數據再次寫入另一個WAV文件。

我已完成閱讀和應用過濾器,但無法編寫WAV文件。 該程序在編譯時沒有給出任何錯誤,但WAV文件不播放。

如果我將"temp"寫入WAV ,它會正常運行。 但如果我寫"data" ,它不會。

如何正確編寫 WAV 文件?

#define _CRT_SECURE_NO_WARNINGS
#define PI 3.14f
#define WAV_HEADER_LENGTH 44

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

char* read_wav(const char* filename, short*, short*, int*);
void write_wav(const char* filename, const char*, int);

using namespace std;

int main()
{
short nchannel, ssample;
int csample;

//Reading WAV file and returning the data.
char* temp = read_wav("sum.wav", &nchannel, &ssample, &csample);
short* data = (short*)&temp[WAV_HEADER_LENGTH];

cout << "How many coefficients are there in filter ?" << endl;
int N;
cin >> N ;

float filter[N];
cout << "Type coefficients in filter." << endl;
for(int i=0; i<N;i++){
    cin >> filter[i];
}

short* output = (short*)&temp[WAV_HEADER_LENGTH];

for(int i=0; i < csample; i++){

    double sum = 0;
    for(int j=0; j < N; j++){
        if((i - j) >= 0)
           sum += filter[j] * data[i-j];
    }
    output[i] = (short) sum;
}

write_wav("test.wav", out, csample * ssample + WAV_HEADER_LENGTH);

}

char* read_wav(const char* filename, short* nchannel, short* ssample, int* csample) {

    //Reading the file.
    FILE* fp = fopen(filename, "rb");

    if (!fp) {
        fprintf(stderr, "Couldn't open the file \"%s\"\n", filename);
        exit(0);
    }

    fseek(fp, 0, SEEK_END);
    int file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    printf("The file \"%s\" has %d bytes\n\n", filename, file_size);

    char* buffer = (char*)malloc(sizeof(char) * file_size);
    fread(buffer, file_size, 1, fp);

    // Dump the buffer info.
    *nchannel = *(short*)&buffer[22];
    *ssample = *(short*)&buffer[34] / 8;
    *csample = *(int*)&buffer[40] / *ssample;

    printf("ChunkSize :\t %u\n", *(int*)&buffer[4]);
    printf("Format :\t %u\n", *(short*)&buffer[20]);
    printf("NumChannels :\t %u\n", *(short*)&buffer[22]);
    printf("SampleRate :\t %u\n", *(int*)&buffer[24]);  // number of samples per second
    printf("ByteRate :\t %u\n", *(int*)&buffer[28]);        // number of bytes per second
    printf("BitsPerSample :\t %u\n", *(short*)&buffer[34]);
    printf("Subchunk2ID :\t \"%c%c%c%c\"\n", buffer[36], buffer[37], buffer[38], buffer[39]);   // marks beginning of the data section
    printf("Subchunk2Size :\t %u\n", *(int*)&buffer[40]);       // size of data (byte)
    printf("Duration :\t %fs\n\n", (float)(*(int*)&buffer[40]) / *(int*)&buffer[28]);

    fclose(fp);
    return buffer;
}

void write_wav(const char* filename, const char* data, int len) {
    FILE* fp = fopen(filename, "wb");

    if (!fp) {
        fprintf(stderr, "Couldn't open the file \"%s\"\n", filename);
        exit(0);
    }

    fwrite(data, len, 1, fp);
    fclose(fp);
}


這對我有用:

int main()
{
    short nchannel, ssample;
    int csample;

    // Reading WAV file and returning the data.
    char* temp = read_wav("sum.wav", &nchannel, &ssample, &csample);
    short* data = (short*)&temp[WAV_HEADER_LENGTH];

//    cout << "How many coefficients are there in filter ?" << endl;
    const int N = 2;
//    cin >> N;

    float filter[N] = {0.5, 0.75};
//    cout << "Type coefficients in filter." << endl;
//    for (int i = 0; i < N; i++)
//    {
//        cin >> filter[i];
//    }

    short* output = (short*)&temp[WAV_HEADER_LENGTH];

    for (int i = 0; i < csample; i++)
    {
        double sum = 0;
        for (int j = 0; j < N; j++)
        {
            if ((i - j) >= 0) sum += filter[j] * data[i - j];
        }
        output[i] = (short)sum;
    }

    write_wav("test.wav", (char*)temp, csample * ssample + WAV_HEADER_LENGTH);
}

我的變化:

  • 主要的變化是使用完整的緩沖區,名稱極具誤導性: temp ,而不是你的out不編譯,作為write_wav的參數。
  • 我應用了“我的”濾波器系數(輸出文件中的聲音真的很失真),
  • 我應用了我最喜歡的縮進

如果代碼是可移植的,您需要檢查字節序並采取相應措施。

我希望輸入和輸出文件的長度相同,但事實並非如此。 請自行檢查為什么不是這種情況。 例子:

-rw-r--r-- 1 zkoza zkoza 787306 06-23 14:09 sum.wav
-rw-r--r-- 1 zkoza zkoza 787176 06-23 14:16 test.wav

輸出文件中似乎缺少 130 個字節。

在編譯時N未知的float filter[N]是 C++ 擴展:請在最終代碼中使用std::vector

下次請提供任何輸入文件的鏈接。 對於我的測試,我使用了https://freewavesamples.com/alesis-fusion-clean-guitar-c3 ,但是所有這些小東西,比如查找輸入文件(WAV 格式有多種風格,我可能錯過了正確的一種) ,猜測過濾器參數等需要時間和精力。

您的條件if ((i - j) >= 0)可以用更容易理解的方式編寫; 最好通過更改內部循環“標題”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM