Hi. A while ago I managed (with your help) to successfully create a method to merge multiple wav files into a single file and this works on Windows great. The problem is I have now moved to OS X and am using NSSpeechSythesizer to perform a similar function but Cocoa saves the audio to AIFF instead and as such I can’t use the same code as it is.
I tried specify a wav file in the NS speaktostring() call but it still saves in AIFF.
Thankfully AIFF is also an open format so it can be traversed but I need a little help:
https://en.wikipedia.org/wiki/Audio_Interchange_File_Format
I know there is FFmpeg out there under LGPL but am not sure I can distribute this in software I am selling so thought maybe it was best to just modify my own code using their source as reference in how to understand the AIFF format.
https://github.com/FFmpeg/FFmpeg/blob/415f907ce8dcca87c9e7cfdc954b92df399d3d80/libavformat/aiff.h
https://github.com/FFmpeg/FFmpeg/blob/adc489adc97faf959f955933d198659f6227adb5/libavcodec/shorten.c
https://github.com/FFmpeg/FFmpeg/blob/64545dd6001355491084902008431e45b3f03c50/libavcodec/g726.c
https://github.com/FFmpeg/FFmpeg/blob/fc9f14c7de5bff05bab6f7b258ca70b777ce04ed/libavformat/aiffenc.c
https://github.com/FFmpeg/FFmpeg/blob/a51867ee6bc717a54ea2436e31ee626f02fdf25d/libavformat/aiffdec.c
The code below is the wav merge routine. Can anyone help me convert this to merge AIFF files instead?
[code]
Dim wavData As MemoryBlock
Dim totalWavData As MemoryBlock
Dim wavStringData As String
Dim bsIn As BinaryStream
Dim bsOut As BinaryStream
Dim i, fileCount As Integer
Dim temp, OutFile As FolderItem
// Files() is an array of FolderItems
fileCount = UBound(Files)
For i = 0 to fileCount
temp = Files(i)
If temp <> Nil and temp.Exists then
// Read the files into memory
bsIn = BinaryStream.Open(temp)
wavData = bsIn.Read(bsIn.Length)
bsIn.Close
// Grab byte point of data chunk label marker
wavStringData = WavData.StringValue(0, WavData.Size)
// Set marker values according to wav header
dataChunkMarker = wavStringData.InstrB("data") - 1 // Subtract 1 for string offset since memory block bytes start at zero index
dataChunkSizeMarker = dataChunkMarker + 4 // Add 4 to acount for starting after "data" label
dataStart = dataChunkMarker + 8 // Add 8 to acount for starting after four byte "data" label and four byte "data hunk size" label
If dataChunkMarker >= 36 then
// Grab actual size of data chunk
dataChunkSize = wavData.UInt32Value(dataChunkSizeMarker)
// Create a new memory block using and modifying the original wav header data
If i = 0 then
// Header should be 44 bytes so use exisiting data to recreate it in case it is not standard
Dim m As new MemoryBlock(44)
Dim Channels, SampleRate, BitsPerSample As Integer
// Grab exisiting data that we can use in new header
Channels = wavData.UInt16Value(22)
SampleRate = wavData.UInt32Value(24)
BitsPerSample = wavData.UInt16Value(34)
// Note: UInt16 = 2 bytes and UInt32 = 4 bytes
m.LittleEndian = True
m.UInt32Value(0) = &h46464952 // “RIFF”
m.Int32Value(4) = wavData.Size - 8 // This will be set again later to correct concatenated size
m.UInt32Value(8) = &h45564157 // “WAVE”
m.UInt32Value(12) = &h20746d66 // "fmt " chunk ID
m.UInt32Value(16) = 16 // fmt chunck size
m.UInt16Value(20) = 1 // PCM
m.UInt16Value(22) = Channels // number of Channels (mono or stereo)
m.UInt32Value(24) = SampleRate // Sample rate, 44100 etc
m.UInt32Value(28) = SampleRate * ((BitsPerSample * Channels) / 8) // 44100 * 1 * 8 / 8 //SampleRate * NumChannels * BitsPerSample/8 //ByteRate
m.UInt16Value(32) = (BitsPerSample * Channels) / 8 // 1 * 8 / 8 //NumChannels * BitsPerSample/8 // Block align
m.UInt16Value(34) = BitsPerSample // Bits per sample (8 bits = 8, 16 bits = 16, etc.)
m.UInt32Value(36) = &h61746164 // “data” chunk ID
m.UInt32Value(40) = wavData.Size // NumSamples * NumChannels * BitsPerSample/8 // data chunk size which will be set again later to correct concatenated size
totalWavData = m
End If
// Add the actual data to the memory block (which will resize itself according to amount of data added)
totalWavData = totalWavData + wavData.MidB(dataStart, dataChunkSize)
End If
End If
Next
// Update the header
fmtChunkSize = totalWavData.Size - 8
dataChunkSize = totalWavData.Size - 44
totalWavData.Int32Value(4) = fmtChunkSize
totalWavData.UInt32Value(40) = dataChunkSize
// Save the joined files to disk
bsOut = BinaryStream.Create(OutFile, True)
bsOut.Write(totalWavData)
bsOut.Close[/code]