单声道WAV在两个频道播放

时间:2015-04-21 05:02:35

标签: c audio wav

我创建了一个随机单声道WAV,但是当我播放它时,我可以通过两个声道(左和右)听到音频。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct wav{
    char ChunkID[4];
    unsigned int ChunkSize;
    char Format[4];
    char Subchunk1ID[4];
    unsigned int Subchunk1Size;
    unsigned short int AudioFormat;
    unsigned short int NumChannels;
    unsigned int SampleRate;
    unsigned int ByteRate;
    unsigned short int BlockAlign;
    unsigned short int BitsPerSample;
    char SubChunk2ID[4];
    unsigned int Subchunk2Size;
};

int main(){

    struct wav wavHdr;
    FILE *fp;

    fp = fopen("MonoSound.wav", "wb");

    strcpy(wavHdr.ChunkID, "RIFF");
    strcpy(wavHdr.Format, "WAVE");
    strcpy(wavHdr.Subchunk1ID, "fmt ");
    wavHdr.Subchunk1Size = 16;
    wavHdr.AudioFormat = 1;
    wavHdr.NumChannels = 1;
    wavHdr.SampleRate = 220505;
    wavHdr.ByteRate = 441010;   //(SampleRate*NumChannels*BitsPerSample/8)
    wavHdr.BlockAlign = 2;     //(NumChannels*BitsPerSample/8)
    wavHdr.BitsPerSample = 16;
    strcpy(wavHdr.SubChunk2ID, "data");
    /* multiplied by 5 because there's 5 seconds of audio */
    wavHdr.Subchunk2Size = (5 * wavHdr.ByteRate);
    wavHdr.ChunkSize = (wavHdr.Subchunk2Size + 36);

    fwrite(&wavHdr, 44, 1, fp);

    int i, randVal;
    unsigned int audio;
    float freq = 50.0;
    int amp = 32600;
    float w;

    srand(time(NULL));

    for(i = 0; i < (5 * wavHdr.SampleRate); i++){
        randVal = (rand() % 1) + 1;
        amp += randVal;
        w = 2.0 * 3.141592 * freq;
        audio = amp * sin(w * i / 220505.0);
        fwrite(&audio, 2, 1, fp);
    }

    return 0;
}

我在这里做错了什么?音频应该只通过其中一个扬声器发出。在此先感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

  

“音频应仅通过其中一个扬声器发出”

不是真的。如果您有单声道文件,即在录制音频时有一个麦克风,您将在两个输出通道上获得相同的数据。如果您只想从一个频道听到音频,请使用2个频道的wav,一个频道全部为零

答案 1 :(得分:2)

  

音频应该只通过其中一个扬声器出现

你为什么这么认为?可能音频驱动程序试图变得智能并通过两个扬声器播放单声道信号(就像所有其他消费类音频硬件一样)。

如果您想确保仅在左声道播放信号,则必须创建立体声信号,并将右声道设置为静音(全零)。

答案 2 :(得分:1)

为了实现您的目标,您可以欺骗您的声卡(默认情况下将单声道文件播放到两个扬声器声道),或者您可以使用一个空声道创建立体声文件。 为此,您必须更改通道数(使用wavHdr.NumChannels设置为2)并且必须与 good 交替编写空通道(请参阅第二个命令)代码末尾的fwrite。)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <cstring>

struct wav{
    char ChunkID[4];
    unsigned int ChunkSize;
    char Format[4];
    char Subchunk1ID[4];
    unsigned int Subchunk1Size;
    unsigned short int AudioFormat;
    unsigned short int NumChannels;
    unsigned int SampleRate;
    unsigned int ByteRate;
    unsigned short int BlockAlign;
    unsigned short int BitsPerSample;
    char SubChunk2ID[4];
    unsigned int Subchunk2Size;
};

int main(){

    struct wav wavHdr;
    FILE *fp;

    fp = fopen("MonoSound.wav", "wb");

    strcpy(wavHdr.ChunkID, "RIFF");
    strcpy(wavHdr.Format, "WAVE");
    strcpy(wavHdr.Subchunk1ID, "fmt ");
    wavHdr.Subchunk1Size = 16;
    wavHdr.AudioFormat = 1;
    wavHdr.NumChannels = 2;
    wavHdr.BitsPerSample = 16;
    wavHdr.SampleRate = 220505;
    wavHdr.ByteRate = wavHdr.SampleRate * wavHdr.NumChannels * wavHdr.BitsPerSample/8;
    wavHdr.BlockAlign = wavHdr.NumChannels * wavHdr.BitsPerSample/8;
    strcpy(wavHdr.SubChunk2ID, "data");
    /* multiplied by 5 because there's 5 seconds of audio */
    wavHdr.Subchunk2Size = (5 * wavHdr.ByteRate);
    wavHdr.ChunkSize = (wavHdr.Subchunk2Size + 36);

    fwrite(&wavHdr, 44, 1, fp);

    int i, randVal;
    unsigned int audio, empty=0;
    float freq = 50.0;
    int amp = 32600;
    float w;

    srand(time(NULL));

    for(i = 0; i < (5 * wavHdr.SampleRate); i++){
        randVal = (rand() % 1) + 1;
        amp += randVal;
        w = 2.0 * 3.141592 * freq;
        audio = amp * sin(w * i / 220505.0);
        // write LEFT channel
        fwrite(&audio, 2, 1, fp);
        // write RIGHT channel
        fwrite(&empty, 2, 1, fp);
    }

    return 0;
}

您编写两个频道的顺序很重要。如果您希望空通道为左通道,则必须反转两个fwrite命令。 此外,您必须更改ByteRateBlockAlign以考虑新频道。