0% found this document useful (0 votes)
100 views

Creating A Stereo WAV File Using C - Stack Overflow

The document discusses generating a stereo WAV audio file in C. It provides code to: 1) Define a WAV header structure and write the header to a file, specifying 2 channels of 16-bit PCM audio. 2) Define a data structure to hold each audio frame with separate left and right samples. 3) Generate sawtooth wave audio data for the left and right channels at different frequencies and amplitudes, and write the interleaved data frames to the WAV file.

Uploaded by

emerson
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
100 views

Creating A Stereo WAV File Using C - Stack Overflow

The document discusses generating a stereo WAV audio file in C. It provides code to: 1) Define a WAV header structure and write the header to a file, specifying 2 channels of 16-bit PCM audio. 2) Define a data structure to hold each audio frame with separate left and right samples. 3) Generate sawtooth wave audio data for the left and right channels at different frequencies and amplitudes, and write the interleaved data frames to the WAV file.

Uploaded by

emerson
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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