Audio-Scan

 view release on metacpan or  search on metacpan

src/id3.c  view on Meta::CPAN

_id3_get_v1_utf8_string(id3info *id3, SV **string, uint32_t len)
{
  uint32_t read = 0;
  char *ptr;
  char *str;

  read = _id3_get_utf8_string(id3, string, len, ISO_8859_1);

  if (read) {
    // Trim spaces from end
    if (*string != NULL) {
      str = SvPVX(*string);
      ptr = str + sv_len(*string);

      while (ptr > str && ptr[-1] == ' ')
        --ptr;

      *ptr = 0;
      SvCUR_set(*string, ptr - str);
    }
  }

  return read;
}

uint32_t
_id3_get_utf8_string(id3info *id3, SV **string, uint32_t len, uint8_t encoding)
{
  uint8_t byteorder = UTF16_BYTEORDER_ANY;
  uint32_t read = 0;
  unsigned char *bptr;

  // Init scratch buffer if necessary
  if ( !id3->utf8->alloc ) {
    // Use a larger initial buffer if reading ISO-8859-1 to avoid
    // always having to allocate a second time
    buffer_init( id3->utf8, encoding == ISO_8859_1 ? len * 2 : len );
  }
  else {
    // Reset scratch buffer
    buffer_clear(id3->utf8);
  }

  if ( *string != NULL ) {
    warn("    !!! string SV is not null: %s\n", SvPVX(*string));
  }

  switch (encoding) {
    case ISO_8859_1:
      read += buffer_get_latin1_as_utf8(id3->buf, id3->utf8, len);
      break;

    case UTF_16BE:
      byteorder = UTF16_BYTEORDER_BE;

    case UTF_16:
      bptr = buffer_ptr(id3->buf);

      switch ( (bptr[0] << 8) | bptr[1] ) {
      case 0xfeff:
        DEBUG_TRACE("    UTF-16 BOM is big-endian\n");
        byteorder = UTF16_BYTEORDER_BE;
        buffer_consume(id3->buf, 2);
        read += 2;
        break;

      case 0xfffe:
        DEBUG_TRACE("    UTF-16 BOM is little-endian\n");
        byteorder = UTF16_BYTEORDER_LE;
        buffer_consume(id3->buf, 2);
        read += 2;
        break;
      }

      /* Bug 14728
        If there is no BOM, assume LE, this is what appears in the wild -andy
      */
      if (byteorder == UTF16_BYTEORDER_ANY) {
        DEBUG_TRACE("    UTF-16 byte order defaulting to little-endian, no BOM\n");
        byteorder = UTF16_BYTEORDER_LE;
      }

      read += buffer_get_utf16_as_utf8(id3->buf, id3->utf8, len - read, byteorder);
      break;

    case UTF_8:
      read += buffer_get_utf8(id3->buf, id3->utf8, len);
      break;

    default:
      break;
  }

  if (read) {
    if ( buffer_len(id3->utf8) ) {
      *string = newSVpv( buffer_ptr(id3->utf8), 0 );
      sv_utf8_decode(*string);
      DEBUG_TRACE("    read utf8 string of %d bytes: %s\n", buffer_len(id3->utf8), SvPVX(*string));
    }
    else {
      DEBUG_TRACE("    empty string\n");
    }
  }

  return read;
}

uint32_t
_id3_parse_rvad(id3info *id3, char const *id, uint32_t size)
{
  unsigned char *rva = buffer_ptr(id3->buf);
  int sign_r = rva[0] & 0x01 ? 1 : -1;
  int sign_l = rva[0] & 0x02 ? 1 : -1;
  int bytes = rva[1] / 8;
  float vol[2];
  float peak[2];
  int i;
  AV *framedata = newAV();

  // Sanity check, first byte must be either 0 or 1, second byte > 0
  if (rva[0] & 0xFE || rva[1] == 0) {
    return 0;
  }

  // Calculated size must match the actual size
  if (size != 2 + (bytes * 4)) {
    return 0;
  }

  rva += 2;

  vol[0] = _varint( rva, bytes ) * sign_r / 256.;
  vol[1] = _varint( rva + bytes, bytes ) * sign_l / 256.;

  peak[0] = _varint( rva + (bytes * 2), bytes );
  peak[1] = _varint( rva + (bytes * 3), bytes );

  // iTunes uses a range of -255 to 255
	// to be -100% (silent) to 100% (+6dB)



( run in 1.627 second using v1.01-cache-2.11-cpan-39bf76dae61 )