bool ADMRIFFFile::PostReadChunks() { bool success = RIFFFile::PostReadChunks(); // after reading of chunks, find chna and axml chunks and decode them // to create an ADM if (success) { RIFFChunk *chna = GetChunk(chna_ID); RIFFChunk *axml = GetChunk(axml_ID); // ensure each chunk is valid if (adm && chna && chna->GetData() && axml && axml->GetData()) { // decode chunks success = adm->Set(chna->GetData(), chna->GetLength(), (const char *)axml->GetData()); #if BBCDEBUG_LEVEL >= 4 { // dump ADM as text std::string str; adm->Dump(str); BBCDEBUG("%s", str.c_str()); } { // dump ADM as XML std::string str; adm->GetAxml(str); BBCDEBUG("%s", str.c_str()); } BBCDEBUG("Audio objects:"); std::vector<const ADMObject *> list; adm->GetObjects(ADMAudioObject::Type, list); uint_t i; for (i = 0; i < list.size(); i++) { BBCDEBUG("%s", list[i]->ToString().c_str()); } #endif } // test for different types of failure else if (!adm) { BBCERROR("Cannot decode ADM, no ADM decoder available"); success = false; } else if (!chna || !axml) { // acceptable failure - chna and/or axml chunk not specified - not an ADM compatible BWF file but open anyway BBCDEBUG("Warning: no chna/axml chunks!"); // if no chna supplied, create default channel mapping using standard definitions if (adm && !chna) { // attempt to find a single audioPackFormat from the standard definitions with the correct number of channels std::vector<const ADMObject *> packFormats, streamFormats; ADMAudioObject *object = adm->CreateObject("Main"); // create audio object for entire file uint_t i; // get a list of pack formats - these will be searched for the pack format with the correct number of channels adm->GetObjects(ADMAudioPackFormat::Type, packFormats); // get a list of stream formats - these will be used to search for track formats and channel formats adm->GetObjects(ADMAudioStreamFormat::Type, streamFormats); // search all pack formats for (i = 0; i < packFormats.size(); i++) { ADMAudioPackFormat *packFormat; if ((packFormat = dynamic_cast<ADMAudioPackFormat *>(const_cast<ADMObject *>(packFormats[i]))) != NULL) { // get channel format ref list - the size of this dictates the number of channels supported by the pack format const std::vector<ADMAudioChannelFormat *>& channelFormatRefs = packFormat->GetChannelFormatRefs(); // if the pack has the correct number of channels if (channelFormatRefs.size() == GetChannels()) { uint_t j; BBCDEBUG("Found pack format '%s' ('%s') for %u channels", packFormat->GetName().c_str(), packFormat->GetID().c_str(), GetChannels()); // add pack format to audio object if (object) object->Add(packFormat); // for each channel, create a track and link pack format to each for (j = 0; j < channelFormatRefs.size(); j++) { ADMAudioChannelFormat *channelFormat = channelFormatRefs[j]; ADMAudioTrack *track; std::string name; // create track if ((track = adm->CreateTrack(j)) != NULL) { uint_t k; track->Add(packFormat); // find stream format that points to the correct channel format and use that to find the trackFormat for (k = 0; k < streamFormats.size(); k++) { ADMAudioStreamFormat *streamFormat; // stream format points to channel format and track format so look for stream format with the correct channel format ref if (((streamFormat = dynamic_cast<ADMAudioStreamFormat *>(const_cast<ADMObject *>(streamFormats[k]))) != NULL) && streamFormat->GetChannelFormatRefs().size() && (streamFormat->GetChannelFormatRefs()[0] == channelFormat) && // check for correct channel format ref streamFormat->GetTrackFormatRefs().size()) // make sure there are some track formats ref'd as well { // get track format ref ADMAudioTrackFormat *trackFormat = streamFormat->GetTrackFormatRefs()[0]; BBCDEBUG("Found stream format '%s' ('%s') which refs channel format '%s' ('%s')", streamFormat->GetName().c_str(), streamFormat->GetID().c_str(), channelFormat->GetName().c_str(), channelFormat->GetID().c_str()); BBCDEBUG("Found stream format '%s' ('%s') which refs track format '%s' ('%s')", streamFormat->GetName().c_str(), streamFormat->GetID().c_str(), trackFormat->GetName().c_str(), trackFormat->GetID().c_str()); // add track format to track track->Add(trackFormat); break; } } // add track to audio object if (object) object->Add(track); } } break; } } } // set default time limits on audio object if (object && filesamples) { BBCDEBUG("Setting duration to %sns", StringFrom(filesamples->GetLengthNS()).c_str()); object->SetDuration(filesamples->GetLengthNS()); } } success = true; } else { // unacceptible failures: empty chna or empty axml chunks if (chna && !chna->GetData()) BBCERROR("Cannot decode ADM, chna chunk not available"); if (axml && !axml->GetData()) BBCERROR("Cannot decode ADM, axml chunk not available"); success = false; } // now that the data is dealt with, the chunk data can be deleted if (axml) axml->DeleteData(); if (chna) chna->DeleteData(); } return success; }