Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

11/07/2017 Creating a stereo WAV file using C - Stack Overflow

xDismiss

FaapartedacomunidadeStack
Overflow

O Stack Overflow uma comunidade com 7.4


milhes de programadores como voc, ajudando
uns aos outros.
Juntese a ns no demora nada:

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.

c file audio wav

editedApr14'14at1:48 askedApr12'14at13:24
Jamal user3526827
559 6 18 27 43 6

AreyoudoingthisonanArduino,orjustyourownlaptopordesktop?SafayetAhmedApr12'14at15:25

I'mdoingthisonmylaptopfornow,planistorunitonasmallLinuxdevice.Thanks user3526827 Apr12


'14at15:43

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

You might also like