Dug up this old class I’d made, basically what Garth said except not all of it. It’s clumsy to use and inefficient (audio data duplicated into second MemoryBlock) but has the basis for header writing.
It should work for mono or stereo, 8 or 16 bit formats. Never tried it with other bit sizes but know it doesn’t handle the 24bit mono case Garth mentioned. Actually that case could happen with 8bit mono too but I never noticed a problem. ymmv
[code]Class WaveSound
Constant Private kHeaderTagRIFF = &h46464952
Constant Private kHeaderTagWAVE = &h45564157
Constant Private kHeaderTagfmt = &h20746D66
Constant Private kHeaderTagdata = &h61746164
Property Private bitsPerSample As Integer
Property Private sampleHz As Integer
Property Private channelCount As Integer
Sub Constructor(channels As integer, sampleBitSize As integer, sampleHertz As integer)
channelCount = channels
bitsPerSample = sampleBitSize
sampleHz = sampleHertz
End Sub
Function createWaveFileData(waveData As MemoryBlock) As MemoryBlock
dim m As new MemoryBlock(44 + waveData.Size) //header is 44 bytes
m.LittleEndian = true
m.UInt32Value(0) = kHeaderTagRIFF
m.Int32Value(4) = m.Size - 8 //total file size minus this
m.UInt32Value(8) = kHeaderTagWAVE
m.UInt32Value(12) = kHeaderTagfmt
m.UInt32Value(16) = 16 //fmt chunck size
m.UInt16Value(20) = 1 //PCM
m.UInt16Value(22) = channelCount
m.UInt32Value(24) = sampleHz
m.UInt32Value(28) = SampleHz * channelCount * bitsPerSample / 8 //ByteRate
m.UInt16Value(32) = channelCount * bitsPerSample / 8 //block align
m.UInt16Value(34) = bitsPerSample
m.UInt32Value(36) = kHeaderTagdata
m.UInt32Value(40) = waveData.Size
m.StringValue(44, waveData.Size) = waveData //copy in samples
return m
End Function
End Class[/code]
example usage writing a file
[code]Sub Action()
//make audio data in a format
dim audioData As MemoryBlock = generateMono16Bit44100hz
//make WaveSound object for same format
dim wav As new WaveSound(1, 16, 44100)
//make file data with audio data
dim fileData As MemoryBlock = wav.createWaveFileData(audioData)
//write file data to file on desktop
dim f As FolderItem = SpecialFolder.Desktop.Child(“500hz.wav”)
dim bs As BinaryStream = BinaryStream.Create(f, true)
bs.Write(fileData)
bs.Close
End Sub
Protected Function generateMono16Bit44100hz() As MemoryBlock
dim sampleRate As integer = 44100
dim sampleCount As integer = sampleRate * 4 //4 seconds worth
dim lastSampleIdx As integer = sampleCount - 1
dim tau As double = 6.283185307179586
dim freqScale As double = (500 / sampleRate) * tau //500hz
dim m As new MemoryBlock(sampleCount * 2) //2 bytes per sample
dim p As Ptr = m
for i As integer = 0 to lastSampleIdx
p.Int16(i*2) = 20000 * sin(i * freqScale)
next
return m
End Function[/code]
here’s some links about the format that helped
http://soundfile.sapp.org/doc/WaveFormat/
http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
http://www.topherlee.com/software/pcm-tut-wavformat.html