Example #1
1
/*--------------------------------------------------------------------------------*/
bool XMLADMData::ReadChnaFromFile(const std::string& filename, bool finalise)
{
  EnhancedFile fp;
  bool success = false;

  if (fp.fopen(filename.c_str()))
  {
    char buffer[1024];
    int l;

    success = true;

    while (success && ((l = fp.readline(buffer, sizeof(buffer) - 1)) != EOF))
    {
      if (l > 0)
      {
        std::vector<std::string> words;

        SplitString(std::string(buffer), words);

        if (words.size() == 4)
        {
          uint_t tracknum;

          if (Evaluate(words[0], tracknum))
          {
            if (tracknum)
            {
              const std::string& trackuid    = words[1];
              const std::string& trackformat = words[2];
              const std::string& packformat  = words[3];
              ADMAudioTrack *track;
              std::string id;

              if ((track = dynamic_cast<ADMAudioTrack *>(Create(ADMAudioTrack::Type, trackuid, ""))) != NULL)
              {
                XMLValue tvalue, pvalue;

                track->SetTrackNum(tracknum - 1);

                tvalue.name = ADMAudioTrackFormat::Reference;
                tvalue.value = trackformat;
                track->AddValue(tvalue);

                pvalue.name = ADMAudioPackFormat::Reference;
                pvalue.value = packformat;
                track->AddValue(pvalue);

                track->SetValues();

                BBCDEBUG2(("Track %u: Index %u UID '%s' TrackFormatRef '%s' PackFormatRef '%s'",
                        (uint_t)tracklist.size(),
                        track->GetTrackNum() + 1,
                        track->GetID().c_str(),
                        tvalue.value.c_str(),
                        pvalue.value.c_str()));
              }
              else
              {
                BBCERROR("Failed to create AudioTrack for UID %u", tracknum);
                success = false;
              }
            }
          }
          else
          {
            BBCERROR("CHNA line '%s' word 1 ('%s') should be a track number", buffer, words[0].c_str());
            success = false;
          }
        }
        else
        {
          BBCERROR("CHNA line '%s' requires 4 words", buffer);
          success = false;
        }
      }
    }

    fp.fclose();

    if (success && finalise) Finalise();
  }

  return success;
}
Example #2
0
/*--------------------------------------------------------------------------------*/
bool XMLADMData::SetChna(const uint8_t *data, uint64_t len)
{
  const CHNA_CHUNK& chna = *(const CHNA_CHUNK *)data;
  uint_t maxuids = (uint_t)((len - sizeof(CHNA_CHUNK)) / sizeof(chna.UIDs[0]));   // calculate maximum number of UIDs given chunk length
  std::string terminator;
  bool success = true;

  // create string with a single 0 byte in it to detect terminators
  terminator.push_back(0);

  if (maxuids < chna.UIDCount) BBCERROR("Warning: chna specifies %u UIDs but chunk has only length for %u", (uint_t)chna.UIDCount, maxuids);

  uint16_t i;
  for (i = 0; (i < chna.UIDCount) && (i < maxuids); i++)
  {
    // only handle non-zero track numbers
    if (chna.UIDs[i].TrackNum)
    {
      ADMAudioTrack *track;
      std::string id;

      id.assign(chna.UIDs[i].UID, sizeof(chna.UIDs[i].UID));
      id = id.substr(0, id.find(terminator));

      // delete any existing ADMAudioTracks of the same ID
      if ((track = dynamic_cast<ADMAudioTrack *>(Create(ADMAudioTrack::Type, id, "", true))) != NULL)
      {
        XMLValue tvalue, pvalue;

        track->SetTrackNum(chna.UIDs[i].TrackNum - 1);

        tvalue.name = ADMAudioTrackFormat::Reference;
        tvalue.value.assign(chna.UIDs[i].TrackRef, sizeof(chna.UIDs[i].TrackRef));
        // trim any zero bytes off the end of the string
        tvalue.value = tvalue.value.substr(0, tvalue.value.find(terminator));
        track->AddValue(tvalue);

        pvalue.name = ADMAudioPackFormat::Reference;
        pvalue.value.assign(chna.UIDs[i].PackRef, sizeof(chna.UIDs[i].PackRef));
        // trim any zero bytes off the end of the string
        pvalue.value = pvalue.value.substr(0, pvalue.value.find(terminator));
        track->AddValue(pvalue);

        track->SetValues();

        BBCDEBUG2(("Track %u/%u: Index %u UID '%s' TrackFormatRef '%s' PackFormatRef '%s'",
                i, (uint_t)tracklist.size(),
                track->GetTrackNum() + 1,
                track->GetID().c_str(),
                tvalue.value.c_str(),
                pvalue.value.c_str()));
      }
      else BBCERROR("Failed to create AudioTrack for UID %u", i);
    }
  }

  SortTracks();

  return success;
}
/*--------------------------------------------------------------------------------*/
void AudioObjectParameters::ToJSON(JSONValue& obj, bool force) const
{
  SetToJSON<>(Parameter_channel, (int)values.channel, obj, force);
  SetToJSON<>(Parameter_duration, (sint64_t)values.duration, obj, force);
  SetToJSON<>(Parameter_cartesian, values.cartesian, obj, force);
  SetToJSON<>(Parameter_position, position, obj, force);
  SetToJSONPtr<>(Parameter_minposition, minposition, obj, force);
  SetToJSONPtr<>(Parameter_maxposition, maxposition, obj, force);
  SetToJSON<>(Parameter_gain, values.gain, obj, force);
  SetToJSON<>(Parameter_width, values.width, obj, force);
  SetToJSON<>(Parameter_depth, values.depth, obj, force);
  SetToJSON<>(Parameter_height, values.height, obj, force);
  SetToJSON<>(Parameter_diffuseness, values.diffuseness, obj, force);
  SetToJSON<>(Parameter_divergencebalance, values.divergencebalance, obj, force);
  SetToJSON<>(Parameter_divergenceazimuth, values.divergenceazimuth, obj, force);
  SetToJSON<>(Parameter_delay, values.delay, obj, force);
  SetToJSON<>(Parameter_objectimportance, (int)values.objectimportance, obj, force);
  SetToJSON<>(Parameter_channelimportance, (int)values.channelimportance, obj, force);
  SetToJSON<>(Parameter_dialogue, (int)values.dialogue, obj, force);
  SetToJSON<>(Parameter_channellock, values.channellock, obj, force);
  SetToJSON<>(Parameter_channellockmaxdistance, values.channellockmaxdistance, obj, force);
  SetToJSON<>(Parameter_interact, values.interact, obj, force);
  SetToJSON<>(Parameter_interpolate, values.interpolate, obj, force);
  SetToJSON<>(Parameter_interpolationtime, (sint64_t)values.interpolationtime, obj, force);
  SetToJSON<>(Parameter_onscreen, values.onscreen, obj, force);
  SetToJSON<>(Parameter_disableducking, values.disableducking, obj, force);
  SetToJSON<>(Parameter_othervalues, othervalues, obj, force);
  
  // output all excluded zones
  const ExcludedZone *zone = GetFirstExcludedZone();
  if (zone)
  {
    JSONValue zones;
    while (zone)
    {
      JSONValue subobj;
      Position c1 = zone->GetMinCorner();
      Position c2 = zone->GetMaxCorner();

      subobj["name"] = zone->GetName();
      subobj["minx"] = c1.pos.x;
      subobj["miny"] = c1.pos.y;
      subobj["minz"] = c1.pos.z;
      subobj["maxx"] = c2.pos.x;
      subobj["maxy"] = c2.pos.y;
      subobj["maxz"] = c2.pos.z;

      zones.append(subobj);
    
      zone = zone->GetNext();
    }

    obj["excludedzones"] = zones;
  }

  BBCDEBUG2(("JSON: %s", ToJSONString(obj, true).c_str()));
}
Example #4
0
/*--------------------------------------------------------------------------------*/
uint8_t *XMLADMData::GetChna(uint64_t& len) const
{
  CHNA_CHUNK *p = NULL;
  uint_t nuids = (uint_t)tracklist.size();

#if CHNA_FIXED_UIDS_LOWER > 0
  nuids = (nuids <= CHNA_FIXED_UIDS_LOWER) ? CHNA_FIXED_UIDS_LOWER : CHNA_FIXED_UIDS_UPPER;
#endif

  // calculate size of chna chunk
  len = sizeof(*p) + (uint64_t)nuids * (uint64_t)sizeof(p->UIDs[0]);
  if ((p = (CHNA_CHUNK *)calloc(1, len)) != NULL)
  {
    std::vector<bool> uniquetracks; // list of unique tracks
    uint_t i;

    // allocate maximum number of tracks
    uniquetracks.resize(tracklist.size());

    // populate structure
    p->TrackCount = 0;
    p->UIDCount   = 0;

    for (i = 0; (i < tracklist.size()) && (p->UIDCount < nuids); i++)
    {
      const ADMAudioTrack *track = tracklist[i];
      uint_t tr = track->GetTrackNum();

      // test to see if uniquetracks array needs expanding
      if (tr >= uniquetracks.size()) uniquetracks.resize(tr + 1);

      // if this is a new track (i.e. one not previously used),increment TrackCount
      if (!uniquetracks[tr])
      {
        // set flag
        uniquetracks[tr] = true;
        // increment TrackCount
        p->TrackCount++;
      }

      // set track number (1- based) and UID
      p->UIDs[i].TrackNum = tr + 1;
      strncpy(p->UIDs[i].UID, track->GetID().c_str(), sizeof(p->UIDs[i].UID));

      // set trackformat references
      const ADMAudioTrackFormat *trackref = NULL;
      if (track->GetTrackFormatRefs().size() && ((trackref = track->GetTrackFormatRefs()[0]) != NULL))
      {
        strncpy(p->UIDs[i].TrackRef, trackref->GetID().c_str(), sizeof(p->UIDs[i].TrackRef));
      }

      // set packformat references
      const ADMAudioPackFormat *packref = NULL;
      if (track->GetPackFormatRefs().size() && ((packref = track->GetPackFormatRefs()[0]) != NULL))
      {
        strncpy(p->UIDs[i].PackRef, packref->GetID().c_str(), sizeof(p->UIDs[i].PackRef));
      }

      p->UIDCount++;

      BBCDEBUG2(("Track %u/%u: Index %u UID '%s' TrackFormatRef '%s' PackFormatRef '%s'",
              i, (uint_t)tracklist.size(),
              track->GetTrackNum() + 1,
              track->GetID().c_str(),
              trackref ? trackref->GetID().c_str() : "<none>",
              packref  ? packref->GetID().c_str()  : "<none>"));
    }
  }

  return (uint8_t *)p;
}
Example #5
0
/*--------------------------------------------------------------------------------*/
void BiQuadCoeffs::CalcCoeffs(Filter_t type, double freq, double fs, double gain, double bandwidth, double interp_time)
{
  double  A, omega, sn, cs, alpha, beta;
  // numerator coeffs
  double& b0 = targets.num0;
  double& b1 = targets.num1;
  double& b2 = targets.num2;
  // denominator coeffs
  double  a0 = 1.0;             // this will be used to normalize the coeffs at the end
  double& a1 = targets.den1;
  double& a2 = targets.den2;

  // setup variables
  A     = pow(10.0, gain / 40.0);
  omega = 2.0 * M_PI * freq / fs;
  sn    = sin(omega);
  cs    = cos(omega);
  alpha = sn * sinh(M_LN2 / 2.0 * bandwidth * omega / sn);
  beta  = sqrt(A + A);

  switch (type)
  {
    default:
    case FLAT:
      // flat
      b0 = 1.0;
      b1 = 0.0;
      b2 = 0.0;
      a0 = 1.0;
      a1 = 0.0;
      a2 = 0.0;
      break;

    case LPF6:
      // lowpass filter (6dB/octave) - NOT from Audio EQ Cookbook
      //          sn
      // = ----------------
      //   (1 + sn) - z(-1)
      b0 = sn;
      b1 = 0;
      b2 = 0;
      a0 = 1 + sn;
      a1 = -1;
      a2 = 0;
      break;

    case LPF12:
      // lowpass filter (12dB/octave) - NOT from Audio EQ Cookbook
      //          sn                 sn                           sn^2
      // = ---------------- . ---------------- = -------------------------------------
      //   (1 + sn) - z(-1)   (1 + sn) - z(-1)   (1 + sn)^2 - 2.(1 + sn).z(-1) + z(-2)
      b0 = sn * sn;
      b1 = 0;
      b2 = 0;
      a0 = (1 + sn) * (1 + sn);
      a1 = -2 * (1 + sn);
      a2 = 1;
      break;

    case HPF6:
      // highpass filter (6dB/octave) - NOT from Audio EQ Cookbook
      //       1 - z(-1)
      // = ------------------
      //   1 - (1 - sn).z(-1)
      b0 = 1;
      b1 = -1;
      b2 = 0;
      a0 = 1;
      a1 = -(1 - sn);
      a2 = 0;
      break;

    case HPF12:
      // highpass filter (12dB/octave) - NOT from Audio EQ Cookbook
      //        1 - z(-1)            1 - z(-1)                 1 - 2.z(-1) + z(-2)
      // = ------------------ . ------------------ = ---------------------------------------
      //   1 - (1 - sn).z(-1)   1 - (1 - sn).z(-1)   1 - 2.(1 - sn).z(-1) + (1 - sn)^2.z(-2)
      b0 = 1;
      b1 = -2;
      b2 = 1;
      a0 = 1;
      a1 = -2 * (1 - sn);
      a2 = (1 - sn) * (1 - sn);
      break;

    case BPF:
      // bandpass filter
      b0 = alpha;
      b1 = 0;
      b2 = -alpha;
      a0 = 1 + alpha;
      a1 = -2 * cs;
      a2 = 1 - alpha;
      break;

    case NOTCH:
      // notch reject filter
      b0 = 1;
      b1 = -2 * cs;
      b2 = 1;
      a0 = 1 + alpha;
      a1 = -2 * cs;
      a2 = 1 - alpha;
      break;

    case PEQ:
      // peaking filter
      b0 = 1 + (alpha * A);
      b1 = -2 * cs;
      b2 = 1 - (alpha * A);
      a0 = 1 + (alpha / A);
      a1 = -2 * cs;
      a2 = 1 - (alpha / A);
      break;

    case LSH:
      // lowshelf filter
      b0 = A * ((A + 1) - (A - 1) * cs + beta * sn);
      b1 = 2 * A * ((A - 1) - (A + 1) * cs);
      b2 = A * ((A + 1) - (A - 1) * cs - beta * sn);
      a0 = (A + 1) + (A - 1) * cs + beta * sn;
      a1 = -2 * ((A - 1) + (A + 1) * cs);
      a2 = (A + 1) + (A - 1) * cs - beta * sn;
      break;

    case HSH:
      // highshelf filter
      b0 = A * ((A + 1) + (A - 1) * cs + beta * sn);
      b1 = -2 * A * ((A - 1) + (A + 1) * cs);
      b2 = A * ((A + 1) + (A - 1) * cs - beta * sn);
      a0 = (A + 1) - (A - 1) * cs + beta * sn;
      a1 = 2 * ((A - 1) - (A + 1) * cs);
      a2 = (A + 1) - (A - 1) * cs - beta * sn;
      break;
  }

  {
    // normalize coeffs
    double normalise = 1.0 / a0;
    b0 *= normalise;
    b1 *= normalise;
    b2 *= normalise;
    a1 *= normalise;
    a2 *= normalise;
  }

  // calculate differences between current and target for interpolation
  diffs.num0 = targets.num0 - current.num0;
  diffs.num1 = targets.num1 - current.num1;
  diffs.num2 = targets.num2 - current.num2;
  diffs.den1 = targets.den1 - current.den1;
  diffs.den2 = targets.den2 - current.den2;

  if (interp_time > 0.0)
  {
    // set initial multiplier and decrement rate
    mul = 1.0;
    dec = 1.0 / (interp_time * fs);
  }
  else
  {
    // zero time interpolation - just set multiplier at zero and current to targets
    mul = dec = 0.0;
    current = targets;
  }

  BBCDEBUG2(("Coeffs: type %u freq %0.1lfHz gain %0.1lfdB bw %0.6lfHz -> {%0.6lf, %0.6lf, %0.6lf, %0.6lf, %0.6lf}",
          (uint_t)type, freq, gain, bandwidth,
          b0, b1, b2, a1, a2));

#if BBCDEBUG_LEVEL >= 3
  {
    // write response out to file
    EnhancedFile fp("coeffs.dat", "w");
    double fs     = 48000.0;
    double f1     = 10.0, f2 = 22000.0;
    double frange = log(f2 / f1);
    uint_t i, steps = 1000;

    for (i = 0; i < steps; i++)
    {
      double p = (double)i / (double)(steps - 1);
      double f = f1 * exp(p * frange);
      
      double gain = CalcResponse(f, fs);

      fp.fprintf("%u %0.1lf %0.4le\n", i, f, gain);
    }
  }
#endif
}