void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
{
  const int end = data.size();
  if(end < 7) {
    debug("A synchronized lyrics frame must contain at least 7 bytes.");
    return;
  }

  d->textEncoding = String::Type(data[0]);
  d->language = data.mid(1, 3);
  d->timestampFormat = TimestampFormat(data[4]);
  d->type = Type(data[5]);

  int pos = 6;

  d->description = readStringField(data, d->textEncoding, &pos);
  if(d->description.isEmpty())
    return;

  /*
   * If UTF16 strings are found in SYLT frames, a BOM may only be
   * present in the first string (content descriptor), and the strings of
   * the synchronized text have no BOM. Here the BOM is read from
   * the first string to have a specific encoding with endianness for the
   * case of strings without BOM so that readStringField() will work.
   */
  String::Type encWithEndianness = d->textEncoding;
  if(d->textEncoding == String::UTF16) {
    unsigned short bom = data.toUShort(6, true);
    if(bom == 0xfffe) {
      encWithEndianness = String::UTF16LE;
    } else if(bom == 0xfeff) {
      encWithEndianness = String::UTF16BE;
    }
  }

  d->synchedText.clear();
  while(pos < end) {
    String::Type enc = d->textEncoding;
    // If a UTF16 string has no BOM, use the encoding found above.
    if(enc == String::UTF16 && pos + 1 < end) {
      unsigned short bom = data.toUShort(pos, true);
      if(bom != 0xfffe && bom != 0xfeff) {
        enc = encWithEndianness;
      }
    }
    String text = readStringField(data, enc, &pos);
    if(text.isEmpty() || pos + 4 > end)
      return;

    unsigned int time = data.toUInt(pos, true);
    pos += 4;

    d->synchedText.append(SynchedText(time, text));
  }
}
void Opus::Properties::read(File *file)
{
  // Get the identification header from the Ogg implementation.

  // http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1

  const ByteVector data = file->packet(0);

  // *Magic Signature*
  uint pos = 8;

  // *Version* (8 bits, unsigned)
  d->opusVersion = uchar(data.at(pos));
  pos += 1;

  // *Output Channel Count* 'C' (8 bits, unsigned)
  d->channels = uchar(data.at(pos));
  pos += 1;

  // *Pre-skip* (16 bits, unsigned, little endian)
  const ushort preSkip = data.toUShort(pos, false);
  pos += 2;

  // *Input Sample Rate* (32 bits, unsigned, little endian)
  d->inputSampleRate = data.toUInt(pos, false);
  pos += 4;

  // *Output Gain* (16 bits, signed, little endian)
  pos += 2;

  // *Channel Mapping Family* (8 bits, unsigned)
  pos += 1;

  const Ogg::PageHeader *first = file->firstPageHeader();
  const Ogg::PageHeader *last  = file->lastPageHeader();

  if(first && last) {
    const long long start = first->absoluteGranularPosition();
    const long long end   = last->absoluteGranularPosition();

    if(start >= 0 && end >= 0) {
      const long long frameCount = (end - start - preSkip);

      if(frameCount > 0) {
        const double length = frameCount * 1000.0 / 48000.0;
        d->length  = static_cast<int>(length + 0.5);
        d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
      }
    }
    else {
      debug("Opus::Properties::read() -- The PCM values for the start or "
            "end of this file was incorrect.");
    }
  }
  else
    debug("Opus::Properties::read() -- Could not find valid first and last Ogg pages.");
}
Exemple #3
0
int ASF::File::readWORD(bool *ok)
{
  ByteVector v = readBlock(2);
  if(v.size() != 2) {
    if(ok) *ok = false;
    return 0;
  }
  if(ok) *ok = true;
  return v.toUShort(false);
}
Exemple #4
0
 uint read(TagLib::File &file, uint limit)
 {
   ByteVector data = file.readBlock(std::min(2U,limit));
   value = data.toUShort(bigEndian);
   return data.size();
 }