在两个通道上播放单声道 WAV
Mono WAV playing on both channels
我创建了一个随机的单声道 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;
}
我做错了什么?音频只能通过其中一个扬声器输出。在此先感谢您的帮助。
"The audio should only come out through one of the speakers"
不是真的。当你有单声道文件时,即你在录制音频时有一个麦克风,你将在两个输出通道上获得相同的数据。如果你只想听到一个通道的音频,制作 2 个通道的 wav,其中一个通道全为零
The audio should only come out through one of the speakers
你为什么这么认为?可能音频驱动程序试图变得聪明并通过两个扬声器播放单声道信号(就像所有其他消费类音频硬件一样)。
如果您想确保只在左声道播放信号,您必须创建一个立体声信号并将右声道设置为静音(全为零) .
为了实现您的目标,您可以欺骗您的声卡(默认情况下将单声道文件播放到两个扬声器声道),或者您可以创建一个具有一个空声道的立体声文件。
为此,您必须更改通道数(使用 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
命令。
此外,您必须更改 ByteRate
和 BlockAlign
以考虑新频道。
我创建了一个随机的单声道 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;
}
我做错了什么?音频只能通过其中一个扬声器输出。在此先感谢您的帮助。
"The audio should only come out through one of the speakers"
不是真的。当你有单声道文件时,即你在录制音频时有一个麦克风,你将在两个输出通道上获得相同的数据。如果你只想听到一个通道的音频,制作 2 个通道的 wav,其中一个通道全为零
The audio should only come out through one of the speakers
你为什么这么认为?可能音频驱动程序试图变得聪明并通过两个扬声器播放单声道信号(就像所有其他消费类音频硬件一样)。
如果您想确保只在左声道播放信号,您必须创建一个立体声信号并将右声道设置为静音(全为零) .
为了实现您的目标,您可以欺骗您的声卡(默认情况下将单声道文件播放到两个扬声器声道),或者您可以创建一个具有一个空声道的立体声文件。
为此,您必须更改通道数(使用 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
命令。
此外,您必须更改 ByteRate
和 BlockAlign
以考虑新频道。