/*--------------------------------------------------------------------------------*/ bool AudioObjectParameters::operator == (const AudioObjectParameters& obj) const { bool same = ((position == obj.position) && (memcmp(&values, &obj.values, sizeof(obj.values)) == 0) && Compare(excludedZones, obj.excludedZones) && (GetMinPosition() == obj.GetMinPosition()) && (GetMaxPosition() == obj.GetMaxPosition()) && (othervalues == obj.othervalues)); #if BBCDEBUG_LEVEL>=4 if (!same) { BBCDEBUG("Compare: %u/%u/%u/%u/%08x/%08x", (uint_t)(position == obj.position), (uint_t)(memcmp(&values, &obj.values, sizeof(obj.values)) == 0), (uint_t)Compare(excludedZones, obj.excludedZones), (uint_t)(othervalues == obj.othervalues), setbitmap, obj.setbitmap); std::string line; const uint8_t *p1 = (const uint8_t *)&values, *p2 = (const uint8_t *)&obj.values; uint_t i; for (i = 0; i < sizeof(values); i++) { if (line.empty()) { Printf(line, "%04x:", i); } Printf(line, " %02x/%02x", (uint_t)p1[i], (uint_t)p2[i]); if ((i & 7) == 7) { BBCDEBUG("%s", line.c_str()); line = ""; } } if (!line.empty()) BBCDEBUG("%s", line.c_str()); } #endif return same; }
/*--------------------------------------------------------------------------------*/ void AudioObjectParameters::Interpolate(AudioObjectParameters& dst, double mul, const AudioObjectParameters& a, const AudioObjectParameters& b) { dst = (mul >= .5f) ? a : b; // best initial value for non-interpolatable parameters // now modify parameters that are interpolatable // outside of the endstops, actually interpolate if ((mul > 0.0) && (mul < 1.0)) { // merge bitmaps of parameters set so that if parameter is set in *either* a or b it will be interpolated dst.setbitmap = a.setbitmap | b.setbitmap; if (dst.IsParameterSet(Parameter_position)) { dst.Interpolate(Parameter_position, mul, dst.position, &a.position, &b.position); } if (dst.IsParameterSet(Parameter_minposition)) { if (!dst.minposition) dst.minposition = new Position; dst.Interpolate(Parameter_minposition, mul, *dst.minposition, a.minposition, b.minposition); } if (dst.IsParameterSet(Parameter_maxposition)) { if (!dst.maxposition) dst.maxposition = new Position; dst.Interpolate(Parameter_maxposition, mul, *dst.maxposition, a.maxposition, b.maxposition); } dst.Interpolate<>(Parameter_gain, mul, dst.values.gain, a.values.gain, b.values.gain); dst.Interpolate<>(Parameter_width, mul, dst.values.width, a.values.width, b.values.width); dst.Interpolate<>(Parameter_height, mul, dst.values.height, a.values.height, b.values.height); dst.Interpolate<>(Parameter_depth, mul, dst.values.depth, a.values.depth, b.values.depth); dst.Interpolate<>(Parameter_divergencebalance, mul, dst.values.divergencebalance, a.values.divergencebalance, b.values.divergencebalance); dst.Interpolate<>(Parameter_divergenceazimuth, mul, dst.values.divergenceazimuth, a.values.divergenceazimuth, b.values.divergenceazimuth); dst.Interpolate<>(Parameter_diffuseness, mul, dst.values.diffuseness, a.values.diffuseness, b.values.diffuseness); dst.Interpolate<>(Parameter_channellockmaxdistance, mul, dst.values.channellockmaxdistance, a.values.channellockmaxdistance, b.values.channellockmaxdistance); } }
int main(int argc, char *argv[]) { // print library versions (the actual loaded versions, if dynamically linked) printf("Versions:\n%s\n", LoadedVersions::Get().GetVersionsList().c_str()); if (argc < 2) { fprintf(stderr, "Usage: write-separate-adm <filename>\n"); exit(1); } // create basic ADM XMLADMData *adm; if ((adm = XMLADMData::CreateADM()) != NULL) { ADMData::OBJECTNAMES names; // set programme name // if an audioProgramme object of this name doesn't exist, one will be created names.programmeName = "ADM Test Programme"; // set content name // if an audioContent object of this name doesn't exist, one will be created names.contentName = "ADM Test Content"; // create 16 tracks, channels and streams uint_t t, ntracks = 16; for (t = 0; t < ntracks; t++) { ADMAudioTrack *track; std::string trackname; printf("------------- Track %2u -----------------\n", t + 1); // create default audioTrackFormat name (used for audioStreamFormat objects as well) Printf(trackname, "Track %u", t + 1); names.trackNumber = t; // create audioTrackUID for chna chunk if ((track = adm->CreateTrack(names.trackNumber)) != NULL) { track->SetSampleRate(48000); track->SetBitDepth(24); } // derive channel and stream names from track name names.channelFormatName = trackname; names.streamFormatName = "PCM_" + trackname; names.trackFormatName = "PCM_" + trackname; // set object name // create 4 objects, each of 4 tracks names.objectName = ""; // need this because Printf() APPENDS! Printf(names.objectName, "Object %u", 1 + (t / 4)); // set pack name from object name // create 4 packs, each of 4 tracks names.packFormatName = ""; // need this because Printf() APPENDS! Printf(names.packFormatName, "Pack %u", 1 + (t / 4)); adm->CreateObjects(names); // note how the programme and content names are left in place in 'names' // this is necessary to ensure that things are linked up properly // find channel format object for this track ADMAudioChannelFormat *cf; if ((cf = dynamic_cast<ADMAudioChannelFormat *>(adm->GetWritableObjectByName(names.channelFormatName, ADMAudioChannelFormat::Type))) != NULL) { // found channel format, generate block formats for it ADMAudioBlockFormat *bf; uint_t i; for (i = 0; i < 20; i++) { if ((bf = adm->CreateBlockFormat(cf)) != NULL) { AudioObjectParameters params; Position pos; // set start time to be index * 25ms bf->SetRTime(i * 25000000); // set duration to be 25ms bf->SetDuration(25000000); pos.polar = true; pos.pos.az = fmod((double)(t + i) * 20.0, 360.0); pos.pos.el = (double)i / (double)ntracks * 60.0; pos.pos.d = 1.0; params.SetPosition(pos); params.SetGain(2.0); params.SetWidth(5.0); params.SetHeight(10.0); params.SetDepth(15.0); params.SetDiffuseness(20.0); params.SetDelay(25.0); params.SetObjectImportance(5); params.SetChannelImportance(2); params.SetDialogue(1); params.SetChannelLock(true); params.SetInteract(true); params.SetInterpolate(true); params.SetInterpolationTimeS(5.2); params.SetOnScreen(true); ParameterSet othervalues = params.GetOtherValues(); params.SetOtherValues(othervalues.Set("other1", 1).Set("other2", "2")); // set object parameters bf->GetObjectParameters() = params; } else fprintf(stderr, "Failed to create audioBlockFormat (t: %u, i: %u)\n", t, i); } } else { // this will only occur in the case of an error fprintf(stderr, "Unable to find channel format '%s'\n", names.channelFormatName.c_str()); } } // finalise ADM adm->Finalise(); // output ADM std::string axml = adm->GetAxml(); printf("XML:\n%s", axml.c_str()); // create simple WAV file RIFFFile file; if (file.Create(argv[1], 48000, 16)) { // add the chna and axml chunks from the ADM uint64_t len; const uint8_t *data; // add chna chunk if ((data = adm->GetChna(len)) != NULL) file.AddChunk("chna", data, len); else fprintf(stderr, "No chna chunk to add!\n"); // add axml chunk file.AddChunk("axml", (const uint8_t *)axml.c_str(), axml.size()); // write everything file.Close(); } else fprintf(stderr, "Failed to create file '%s'\n", argv[1]); } else fprintf(stderr, "Failed to create ADM - no provider available?\n"); return 0; }
/*--------------------------------------------------------------------------------*/ AudioObjectParameters operator * (const AudioObjectParameters& obj, const PositionTransform& transform) { AudioObjectParameters res = obj; res.SetPosition(obj.GetPosition() * transform); return res; }
int main(void) { // print library versions (the actual loaded versions, if dynamically linked) printf("Versions:\n%s\n", LoadedVersions::Get().GetVersionsList().c_str()); XMLADMData *adm; // create basic ADM if ((adm = XMLADMData::CreateADM()) != NULL) { ADMData::OBJECTNAMES names; // set programme name // if an audioProgramme object of this name doesn't exist, one will be created names.programmeName = "ADM Test Programme"; // set content name // if an audioContent object of this name doesn't exist, one will be created names.contentName = "ADM Test Content"; // create 16 tracks, channels and streams uint_t t, ntracks = 16; for (t = 0; t < ntracks; t++) { std::string trackname; printf("------------- Track %2u -----------------\n", t + 1); // create default audioTrackFormat name (used for audioStreamFormat objects as well) Printf(trackname, "Track %u", t + 1); names.trackNumber = t; // derive channel and stream names from track name names.channelFormatName = trackname; names.streamFormatName = "PCM_" + trackname; names.trackFormatName = "PCM_" + trackname; // set object name // create 4 objects, each of 4 tracks names.objectName = ""; // need this because Printf() APPENDS! Printf(names.objectName, "Object %u", 1 + (t / 4)); // set pack name from object name // create 4 packs, each of 4 tracks names.packFormatName = ""; // need this because Printf() APPENDS! Printf(names.packFormatName, "Pack %u", 1 + (t / 4)); adm->CreateObjects(names); // note how the programme and content names are left in place in 'names' // this is necessary to ensure that things are linked up properly // find channel format object for this track ADMAudioChannelFormat *cf; if ((cf = dynamic_cast<ADMAudioChannelFormat *>(adm->GetWritableObjectByName(names.channelFormatName, ADMAudioChannelFormat::Type))) != NULL) { // found channel format, generate block formats for it ADMAudioBlockFormat *bf; uint_t i; for (i = 0; i < 20; i++) { if ((bf = adm->CreateBlockFormat(cf)) != NULL) { AudioObjectParameters params; Position pos; // set start time to be index * 25ms bf->SetRTime(i * 25000000); // set duration to be 25ms bf->SetDuration(25000000); pos.polar = true; pos.pos.az = fmod((double)(t + i) * 20.0, 360.0); pos.pos.el = (double)i / (double)ntracks * 60.0; pos.pos.d = 1.0; params.SetPosition(pos); params.SetGain(2.0); params.SetWidth(5.0); params.SetHeight(10.0); params.SetDepth(15.0); params.SetDiffuseness(20.0); params.SetDelay(25.0); params.SetObjectImportance(5); params.SetChannelImportance(2); params.SetDialogue(1); params.SetChannelLock(true); params.SetInteract(true); params.SetInterpolate(true); params.SetInterpolationTimeS(5.2); params.SetOnScreen(true); ParameterSet othervalues = params.GetOtherValues(); params.SetOtherValues(othervalues.Set("other1", 1).Set("other2", "2")); // set object parameters bf->GetObjectParameters() = params; } else fprintf(stderr, "Failed to create audioBlockFormat (t: %u, i: %u)\n", t, i); } } else { // this will only occur in the case of an error fprintf(stderr, "Unable to find channel format '%s'\n", names.channelFormatName.c_str()); } } // finalise ADM adm->Finalise(); // output ADM printf("XML:\n%s", adm->GetAxml().c_str()); } return 0; }
int main(void) { // ensure libraries are set up bbcat_register_bbcat_fileio(); // ADM aware WAV file ADMRIFFFile file; const char *filename = "adm-4gb-bwf.wav"; // IMPORTANT: create basic ADM here - if this is not done, the file will be a plain WAV file! file.CreateADM(); // create file if (file.Create(filename, 48000, 32)) { ADMData *adm = file.GetADM(); if (adm) { ADMData::OBJECTNAMES names; printf("Created '%s' okay, %u channels at %luHz (%u bytes per sample)\n", filename, file.GetChannels(), (ulong_t)file.GetSampleRate(), (uint_t)file.GetBytesPerSample()); // set programme name // if an audioProgramme object of this name doesn't exist, one will be created names.programmeName = "ADM Test Programme"; // set content name // if an audioContent object of this name doesn't exist, one will be created names.contentName = "ADM Test Content"; // create tracks, channels and streams uint_t t; const ADMData::TRACKLIST& tracklist = adm->GetTrackList(); for (t = 0; t < tracklist.size(); t++) { std::string trackname; printf("------------- Track %2u -----------------\n", t + 1); // create default audioTrackFormat name (used for audioStreamFormat objects as well) Printf(trackname, "Track %u", t + 1); names.trackNumber = t; // derive channel and stream names from track name names.channelFormatName = trackname; names.streamFormatName = "PCM_" + trackname; names.trackFormatName = "PCM_" + trackname; // set object name // create 4 objects, each of 4 tracks names.objectName = ""; // need this because Printf() APPENDS! Printf(names.objectName, "Object %u", 1 + (t / 4)); // set pack name from object name // create 4 packs, each of 4 tracks names.packFormatName = ""; // need this because Printf() APPENDS! Printf(names.packFormatName, "Pack %u", 1 + (t / 4)); // set default typeLabel names.typeLabel = ADMObject::TypeLabel_Objects; adm->CreateObjects(names); // note how the programme and content names are left in place in 'names' // this is necessary to ensure that things are linked up properly } } else fprintf(stderr, "File does not have an ADM associated with it, did you forget to create one?\n"); // write audio const uint_t nchannels = file.GetChannels(); std::vector<sint32_t> audio; double fs = (double)file.GetSampleRate(); double level = dBToGain(-40.0); uint64_t i, nsamples = (uint64_t)1000 * (uint64_t)file.GetSampleRate(); uint_t step = file.GetSampleRate() * 10; uint_t j, pc = ~0; UNUSED_PARAMETER(fs); UNUSED_PARAMETER(level); audio.resize(step * nchannels); // write 1000s worth of samples for (i = 0; i < nsamples; i += step) { { uint_t index = (uint_t)(i / step); for (j = 0; j < nchannels; j++) { AudioObjectParameters params; Position pos; pos.polar = true; pos.pos.az = (double)(index + j) * 20.0; pos.pos.el = (double)j / (double)file.GetChannels() * 60.0; pos.pos.d = 1.0; params.SetPosition(pos); // set some extra parameters params.SetWidth((float)j * .2); params.SetDepth((float)j * .4); params.SetHeight((float)j * .3); if (j < 2) { params.SetScreenEdgeLock("azimuth", j ? "right" : "left"); params.SetScreenEdgeLock("elevation", j ? "bottom" : "top"); } else if (j == 2) { params.AddExcludedZone("left", -1, -1, -1, -.8, 1, 1); params.AddExcludedZone("right", .8, -1, -1, 1.0, 1, 1); } else { params.SetObjectImportance(5 + j - 3); params.SetChannelImportance(2 + j - 3); params.SetInteract(j != 3); params.SetDisableDucking(j == 3); } file.SetObjectParameters(j, params); } } // write a frame of audio file.WriteSamples(&audio[0], 0, nchannels, step); uint_t pc1 = (uint_t)((i * 100) / nsamples); if (pc1 != pc) { pc = pc1; printf("\rWriting... %u%% done", pc); fflush(stdout); } } printf("\n"); file.Close(); } else fprintf(stderr, "Failed to open file '%s' for writing!\n", filename); return 0; }