2015-04-21 12 views
5

Ho creato un WAV mono casuale, ma quando suono, posso sentire l'audio attraverso entrambi i canali (a destra &). Ecco il mio codice:Mono WAV su entrambi i canali

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

Che cosa ho fatto di sbagliato qui? L'audio dovrebbe uscire solo attraverso uno degli altoparlanti. Grazie in anticipo per l'aiuto.

+5

Non sono sicuro, ma mi aspetto che il lettore stia vedendo un file audio mono (1 canale) e riproduca automaticamente su entrambi i canali della scheda audio. (Dopo tutto, come fa a sapere quale singolo diffusore usare?) Penso che quello che vuoi fare sia creare un file wave a 2 canali, ma lasciare i dati per tutti gli zeri di un canale. – DoxyLover

risposta

1

Per raggiungere l'obiettivo è possibile ingannare la propria scheda audio (che di default riproduce il file mono in entrambi i canali dei diffusori), oppure è possibile creare un file stereo con un canale vuoto. Per fare ciò è necessario modificare il numero di canali (impostato su 2 utilizzando wavHdr.NumChannels) e si deve scrivere un canale vuoto alternato allo buono (vedere il secondo comando fwrite alla fine del codice.)

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

L'ordine in cui si scrivono i due canali è importante. Se si desidera che il canale vuoto sia quello sinistro, è necessario invertire i due comandi fwrite. Inoltre, è necessario modificare ByteRate e BlockAlign per prendere in considerazione il nuovo canale.

+1

Capito. Non sapevo che dovevo azzerare manualmente uno dei canali. Ottima spiegazione. –

3

"L'audio dovrebbe venire solo attraverso uno dei diffusori"

Non

davvero. Quando hai un file mono, cioè un microfono quando stavi registrando l'audio, riceverai gli stessi dati su entrambi i canali di uscita. Se si desidera ascoltare solo l'audio da un canale rendere wav a 2 canali, con un canale di tutti gli zeri

2

L'audio dovrebbe venire solo attraverso uno dei diffusori

Perché voi pensate così? Probabilmente il driver audio cerca di essere intelligente e riproduce segnali mono attraverso entrambi i diffusori (come tutti gli altri dispositivi audio consumer).

Se si desidera essere certi che un segnale venga riprodotto solo sul canale sinistro, è necessario creare un segnale stereo con il canale destro impostato su Silenzio (tutti zeri).

Problemi correlati