Creating A Stereo WAV File Using C - Stack Overflow
Creating A Stereo WAV File Using C - Stack Overflow
xDismiss
FaapartedacomunidadeStack
Overflow
Entrar
CreatingastereoWAVfileusingC
Iamlookingatcreatinga WAVfileinCandhaveseenanexamplehere.
Thislooksgood,butI'minterestedinaddingtwobufferstomaketheaudiostereo(thepossibilitytohavedifferentsoundineachear).IfI
setthenumberofchannelstotwo,theaudioplaysoutoftheleftchannelonly(whichapparentlyisright,astheleftchannelisthefirst
channel).IhavereadImustinterleaveitwiththerightchannel.
UnfortunatelyIhaven'tfoundmuchonlinetohelpcreateastereoWAV.
write_little_endian((unsignedint)(data[i]),bytes_per_sample,wav_file)
I'vetriedtocreateasecondbuffer,withhalftheamplitudetoseeifIcouldinterleave.
for(j=0i<BUF_SIZEi++){
phase+=freq_radians_per_sample
buffertwo[i]=(int)((amplitude/2)*sin(phase))
}
write_wav("test.wav",BUF_SIZE,buffer,buffertwo,S_RATE)
(changingthefunctiontotaketwoshortintegerbuffers)
Andjustdoing
write_little_endian((unsignedint)(data[i]),bytes_per_sample,wav_file)
write_little_endian((unsignedint)(datatwo[i]),bytes_per_sample,wav_file)
Butthatdoesnotwork.Thatshouldintheorybeinterleaved.
editedApr14'14at1:48 askedApr12'14at13:24
Jamal user3526827
559 6 18 27 43 6
AreyoudoingthisonanArduino,orjustyourownlaptopordesktop?SafayetAhmedApr12'14at15:25
Didyouassignthevariable num_channels=2?Youneedthatforwhenyouwritetheheaderofthewav
filesoitknowsthattherearetwochannelsperframe.nonexApr12'14at15:56
YesIdid,andIalsoresetphase=0beforecallingtheseconditerator.MediaInfoconfirmsIamnow
producinga2channelaudiofile,andthefilesizematchesthebitrate,soIknowbothstreamsarebeing
copiedin. user3526827 Apr12'14at16:11
IknowIdon'tneedtohalveamplitudetodostereo,thisismoretoseeiftheleftandtherightareproducing
differenttonesIwilltrywithoutwrite_little_endianandletyouknow. user3526827 Apr12'14at17:06
2Answers
SoIdecidedtogiveitashotforfunandhereisanalternativewaytowritea.wavfile.It
generatesafilecalled sawtooth_test.wav.Whenyouplayitback,youshouldheartwo
differentfrequenciesfromleftandright.(Don'tplayitbacktooloud.Itsannoying.)
https://stackoverflow.com/questions/23030980/creating-a-stereo-wav-file-using-c 1/4
11/07/2017 Creating a stereo WAV file using C - Stack Overflow
differentfrequenciesfromleftandright.(Don'tplayitbacktooloud.Itsannoying.)
/*CompileswithgccWallO2owavwritewavwrite.c*/
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<limits.h>
/*
TheheaderofawavfileBasedon:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
*/
typedefstructwavfile_header_s
{
charChunkID[4]/*4*/
int32_tChunkSize/*4*/
charFormat[4]/*4*/
charSubchunk1ID[4]/*4*/
int32_tSubchunk1Size/*4*/
int16_tAudioFormat/*2*/
int16_tNumChannels/*2*/
int32_tSampleRate/*4*/
int32_tByteRate/*4*/
int16_tBlockAlign/*2*/
int16_tBitsPerSample/*2*/
charSubchunk2ID[4]
int32_tSubchunk2Size
}wavfile_header_t
/*StandardvaluesforCDqualityaudio*/
#defineSUBCHUNK1SIZE(16)
#defineAUDIO_FORMAT(1)/*ForPCM*/
#defineNUM_CHANNELS(2)
#defineSAMPLE_RATE(44100)
#defineBITS_PER_SAMPLE(16)
#defineBYTE_RATE(SAMPLE_RATE*NUM_CHANNELS*BITS_PER_SAMPLE/8)
#defineBLOCK_ALIGN(NUM_CHANNELS*BITS_PER_SAMPLE/8)
/*Return0onsuccessand1onfailure*/
intwrite_PCM16_stereo_header(FILE*file_p,
int32_tSampleRate,
int32_tFrameCount)
{
intret
wavfile_header_twav_header
int32_tsubchunk2_size
int32_tchunk_size
size_twrite_count
subchunk2_size=FrameCount*NUM_CHANNELS*BITS_PER_SAMPLE/8
chunk_size=4+(8+SUBCHUNK1SIZE)+(8+subchunk2_size)
wav_header.ChunkID[0]='R'
wav_header.ChunkID[1]='I'
wav_header.ChunkID[2]='F'
wav_header.ChunkID[3]='F'
wav_header.ChunkSize=chunk_size
wav_header.Format[0]='W'
wav_header.Format[1]='A'
wav_header.Format[2]='V'
wav_header.Format[3]='E'
wav_header.Subchunk1ID[0]='f'
wav_header.Subchunk1ID[1]='m'
wav_header.Subchunk1ID[2]='t'
wav_header.Subchunk1ID[3]=''
wav_header.Subchunk1Size=SUBCHUNK1SIZE
wav_header.AudioFormat=AUDIO_FORMAT
wav_header.NumChannels=NUM_CHANNELS
wav_header.SampleRate=SampleRate
wav_header.ByteRate=BYTE_RATE
wav_header.BlockAlign=BLOCK_ALIGN
wav_header.BitsPerSample=BITS_PER_SAMPLE
wav_header.Subchunk2ID[0]='d'
wav_header.Subchunk2ID[1]='a'
wav_header.Subchunk2ID[2]='t'
wav_header.Subchunk2ID[3]='a'
wav_header.Subchunk2Size=subchunk2_size
write_count=fwrite(&wav_header,
sizeof(wavfile_header_t),1,
file_p)
ret=(1!=write_count)?1:0
returnret
}
/*Datastructuretoholdasingleframewithtwochannels*/
typedefstructPCM16_stereo_s
{
int16_tleft
int16_tright
}PCM16_stereo_t
https://stackoverflow.com/questions/23030980/creating-a-stereo-wav-file-using-c 2/4
11/07/2017 Creating a stereo WAV file using C - Stack Overflow
}PCM16_stereo_t
PCM16_stereo_t*allocate_PCM16_stereo_buffer(int32_tFrameCount)
{
return(PCM16_stereo_t*)malloc(sizeof(PCM16_stereo_t)*FrameCount)
}
/*Returnthenumberofaudioframessucessfullywritten*/
size_twrite_PCM16wav_data(FILE*file_p,
int32_tFrameCount,
PCM16_stereo_t*buffer_p)
{
size_tret
ret=fwrite(buffer_p,
sizeof(PCM16_stereo_t),FrameCount,
file_p)
returnret
}
/*Generatetwosawtoothsignalsattwofrequenciesandamplitudes*/
intgenerate_dual_sawtooth(doublefrequency1,
doubleamplitude1,
doublefrequency2,
doubleamplitude2,
int32_tSampleRate,
int32_tFrameCount,
PCM16_stereo_t*buffer_p)
{
intret=0
doubleSampleRate_d=(double)SampleRate
doubleSamplePeriod=1.0/SampleRate_d
doublePeriod1,Period2
doublephase1,phase2
doubleSlope1,Slope2
int32_tk
/*CheckfortheviolationoftheNyquistlimit*/
if((frequency1*2>=SampleRate_d)||(frequency2*2>=SampleRate_d))
{
ret=1
gotoerror0
}
/*Computetheperiod*/
Period1=1.0/frequency1
Period2=1.0/frequency2
/*Computetheslope*/
Slope1=amplitude1/Period1
Slope2=amplitude2/Period2
for(k=0,phase1=0.0,phase2=0.0
k<FrameCount
k++)
{
phase1+=SamplePeriod
phase1=(phase1>Period1)?(phase1Period1):phase1
phase2+=SamplePeriod
phase2=(phase2>Period2)?(phase2Period2):phase2
buffer_p[k].left=(int16_t)(phase1*Slope1)
buffer_p[k].right=(int16_t)(phase2*Slope2)
}
error0:
returnret
}
intmain(void)
{
intret
FILE*file_p
doublefrequency1=493.9/*B4*/
doubleamplitude1=0.65*(double)SHRT_MAX
doublefrequency2=392.0/*G4*/
doubleamplitude2=0.75*(double)SHRT_MAX
doubleduration=10/*seconds*/
int32_tFrameCount=duration*SAMPLE_RATE
PCM16_stereo_t*buffer_p=NULL
size_twritten
/*Openthewavfile*/
file_p=fopen("./sawtooth_test.wav","w")
if(NULL==file_p)
{
perror("fopenfailedinmain")
ret=1
gotoerror0
}
/*Allocatethedatabuffer*/
buffer_p=allocate_PCM16_stereo_buffer(FrameCount)
if(NULL==buffer_p)
{
perror("fopenfailedinmain")
https://stackoverflow.com/questions/23030980/creating-a-stereo-wav-file-using-c 3/4
11/07/2017 Creating a stereo WAV file using C - Stack Overflow
perror("fopenfailedinmain")
ret=1
gotoerror1
}
/*Fillthebuffer*/
ret=generate_dual_sawtooth(frequency1,
amplitude1,
frequency2,
amplitude2,
SAMPLE_RATE,
FrameCount,
buffer_p)
if(ret<0)
{
fprintf(stderr,"generate_dual_sawtoothfailedinmain\n")
ret=1
gotoerror2
}
/*Writethewavfileheader*/
ret=write_PCM16_stereo_header(file_p,
SAMPLE_RATE,
FrameCount)
if(ret<0)
{
perror("write_PCM16_stereo_headerfailedinmain")
ret=1
gotoerror2
}
/*Writethedataouttofile*/
written=write_PCM16wav_data(file_p,
FrameCount,
buffer_p)
if(written<FrameCount)
{
perror("write_PCM16wav_datafailedinmain")
ret=1
gotoerror2
}
/*Freeandcloseeverything*/
error2:
free(buffer_p)
error1:
fclose(file_p)
error0:
returnret
}
answeredApr12'14at22:30
SafayetAhmed
408 2 11
Ithinktheproblemiswiththefunction"write_little_endian".Youshouldn'tneedtouseiton
yourlaptop.
Endiannessisarchitecturespecific.TheoriginalexamplewaslikelyforanArduino
microcontrollerboard.ArduinoboardsuseAtmelmicrocontrollerswhicharebigendian.Thats
whythecodeyoucitedexplicitlyneedstoconvertthe16bitintegerstolittleendianformat.
Yourlaptopontheotherhand,usesx86processorswhicharealreadylittleendiansono
conversionisnecessary.Ifyouwantrobustportablecodetoconvertendianness,youcanuse
thefunction htole16inLinux.Lookupthemanpagestolearnmoreaboutthisfunction.
Foraquickbutnonportablefix,Iwouldsayjustwriteouttheentire16bitvalue.
Also,Idon'tthinkyouneedtohalvetheamplitudestogofrommonotostereo.
answeredApr12'14at16:28
SafayetAhmed
408 2 11
https://stackoverflow.com/questions/23030980/creating-a-stereo-wav-file-using-c 4/4