I’m revisiting this issue with more success than my last attempt.
I’m trying to gain access to the markers in audio files too. This is pretty straightforward to read these for both AIFF (‘MARK’ chunk) and WAV ('cue ’ and ‘LIST’ chunks combined).
I’ve written some helper functions to return the seek position for any given chunk name e.g. for example WAV version:
[code]int64 AudioIOHelper::getWavChunkPosition(InputStream* input, const char* name)
{
const int64 originalPosition = input->getPosition();
int64 currentPosition = 0;
input->setPosition(currentPosition);
int64 chunkPosition = -1;
if (input->readInt() == chunkName ("RIFF"))
{
if(chunkName(name) == chunkName ("RIFF"))
{
chunkPosition = currentPosition;
goto exit;
}
const uint32 len = (uint32) input->readInt();
const int64 end = input->getPosition() + len;
currentPosition = input->getPosition();
if (input->readInt() == chunkName ("WAVE"))
{
if(chunkName(name) == chunkName ("WAVE"))
{
chunkPosition = currentPosition;
goto exit;
}
currentPosition = input->getPosition();
while (currentPosition < end && !input->isExhausted())
{
const int chunkType = input->readInt();
if (chunkType == chunkName(name))
{
chunkPosition = currentPosition;
goto exit;
}
uint32 length = (uint32) input->readInt();
const int64 chunkEnd = input->getPosition() + length + (length & 1);
input->setPosition (chunkEnd);
currentPosition = chunkEnd;
}
}
}
exit:
input->setPosition(originalPosition);
return chunkPosition;
}[/code]
So I can easily then go to the relevant chunks and pull out the data. I don’t feel anything here is too hacky (even if it would be more elegant to be part of the WAV and AIFF AudioFormat subclasses).
Writing is more tricky unless someone has a more elegant solution. I can easily write the addition chunks at the end of the file but since the WAV and AIFF AudioFormatWriter subclasses write the header as they are deleted (and these can’t be subclassed as far as I can see, even if that would help) my additional chunks’ sizes can’t be inlcuded in the ‘FORM’/‘RIFF’ headers’ size. Some audio apps kindly read these chunks anway but of course that’s a very poor assumption.
The only thing I can think of doing (which IS hacky) is to
[list]
[]delete the AudioFormatWriter (to allow it to close the stream and write the “incorrect” header) [/]
[]reopen the file as an InputStream, seek to position 4 (where the ‘FORM’/RIFF’ size is), and read the size it thinks it is, then delete that stream[/]
[]reopen the file as an OuputStream, seek to position 4 and write the original size, plus the size of my additional chunk(s), then delete that stream[/][/list]
E.g., for WAV format:
[code]void AudioIOHelper::writeWavCuePoints(AudioFormatWriter* &writer, FileOutputStream* output, MyCuePointData const& cues)
{
uint32 sizeWritten = 0;
… write the additional chunks, keeping track of the sizeWritten …
if(sizeWritten > 0)
{
File file = output->getFile();
delete writer; // force the file to close and write the (incorrect) header
writer = 0; // zero the caller's writer
// find the current size it wrote to the header
FileInputStream* input = file.createInputStream();
input->setPosition(4);
uint32 originalSize = input->readInt();
delete input;
output = file.createOutputStream();
// write the new header adding on our additional content
output->setPosition(4);
output->writeInt(originalSize + sizeWritten);
delete output;
}
}
[/code]
This works but it’s not elegant and I can forsee it creating problems if not careful.