2015-04-21 4 views
5

Ich habe eine zufällige Mono WAV erstellt, aber wenn ich es spiele, kann ich das Audio über beide Kanäle hören (links & rechts). Hier ist mein Code:Mono WAV spielt auf beiden Kanälen

#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; 
} 

Was ich hier falsch gemacht? Der Ton sollte nur über einen der Lautsprecher ausgegeben werden. Vielen Dank im Voraus für die Hilfe.

+5

Ich bin mir nicht sicher, aber ich würde erwarten, dass Ihr Player eine Mono-Audiodatei (1 Kanal) sieht und automatisch auf beiden Soundkarten-Kanälen spielt. (Wie weiß man schließlich, welcher einzelne Lautsprecher verwendet wird?) Ich denke, Sie möchten eine 2-Kanal-Wave-Datei erstellen, aber die Daten für einen Kanal nur Nullen lassen. – DoxyLover

Antwort

1

Um Ihr Ziel zu erreichen, können Sie entweder Ihre Audiokarte austricksen (indem Sie die Monodatei standardmäßig in beide Lautsprecherkanäle spielen), oder Sie können eine Stereodatei mit einem leeren Kanal erstellen. Dazu müssen Sie die Anzahl der Kanäle ändern (mit wavHdr.NumChannels auf 2 setzen) und Sie müssen einen leeren Kanal abwechselnd mit dem guten eins schreiben (siehe den zweiten Befehl fwrite am Ende des Codes).)

#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; 
} 

Die Reihenfolge, in der Sie die zwei Kanalangelegenheiten schreiben. Wenn Sie möchten, dass der leere Kanal der linke Kanal ist, müssen Sie die beiden fwrite Befehle invertieren. Außerdem müssen Sie ByteRate und BlockAlign ändern, um den neuen Kanal zu berücksichtigen.

+1

Bekam es. Ich wusste nicht, dass ich einen der Kanäle manuell auf Null setzen musste. Tolle Erklärung. –

3

„Das Audio sollte nur kommen durch einen des Lautsprechers“ wirklich

nicht. Wenn Sie eine Mono-Datei haben, d. H. Sie hatten ein Mikrofon, als Sie das Audio aufnahmen, erhalten Sie dieselben Daten auf beiden Ausgangskanälen. Wenn Sie möchten, Ton hören nur von einem Kanal 2 Kanal wav machen, mit einem Kanal alle Nullen

2

Die Audio nur durch einen der Lautsprecher kommen sollte

Warum denken Sie so? Wahrscheinlich versucht der Audio-Treiber, smart zu sein und Mono-Signale über beide Lautsprecher (wie alle anderen Verbraucher-Audio-Hardware) zu spielen.

Wenn Sie sicherstellen möchten, dass ein Signal nur auf dem linken Kanal wiedergegeben wird, müssen Sie ein Stereosignal mit dem rechten Kanal auf Stille (alle Nullen) erstellen.