/* Fill info structure with data from aac comments */ static void aac_info (const char *file_name, struct file_tags *info, const int tags_sel) { if (tags_sel & TAGS_COMMENTS) { struct id3_tag *tag; struct id3_file *id3file; char *track = NULL; id3file = id3_file_open (file_name, ID3_FILE_MODE_READONLY); if (!id3file) return; tag = id3_file_tag (id3file); if (tag) { info->artist = get_tag (tag, ID3_FRAME_ARTIST); info->title = get_tag (tag, ID3_FRAME_TITLE); info->album = get_tag (tag, ID3_FRAME_ALBUM); track = get_tag (tag, ID3_FRAME_TRACK); if (track) { char *end; info->track = strtol (track, &end, 10); if (end == track) info->track = -1; free (track); } } id3_file_close (id3file); } if (tags_sel & TAGS_TIME) { struct aac_data *data; data = aac_open_internal (NULL, file_name); if (data->ok) info->time = aac_count_time (data); else logit ("%s", decoder_error_text (&data->error)); aac_close (data); } }
static void *aac_open (const char *file) { struct aac_data *data; data = aac_open_internal (NULL, file); if (data->ok) { int duration = -1; int avg_bitrate = -1; off_t file_size; duration = aac_count_time (data); file_size = io_file_size (data->stream); if (duration > 0 && file_size != -1) avg_bitrate = file_size / duration * 8; aac_close (data); data = aac_open_internal (NULL, file); data->duration = duration; data->avg_bitrate = avg_bitrate; } return data; }
static void *aac_open_internal (struct io_stream *stream, const char *fname) { struct aac_data *data; NeAACDecConfigurationPtr neaac_cfg; int n; /* init private struct */ data = (struct aac_data *)xmalloc (sizeof(struct aac_data)); memset (data, 0, sizeof(struct aac_data)); data->ok = 0; data->decoder = NeAACDecOpen(); /* set decoder config */ neaac_cfg = NeAACDecGetCurrentConfiguration(data->decoder); neaac_cfg->outputFormat = FAAD_FMT_16BIT; /* force 16 bit audio */ neaac_cfg->downMatrix = 1; /* 5.1 -> stereo */ neaac_cfg->dontUpSampleImplicitSBR = 0; /* upsample, please! */ NeAACDecSetConfiguration(data->decoder, neaac_cfg); if (stream) data->stream = stream; else { data->stream = io_open (fname, 1); if (!io_ok(data->stream)) { decoder_error (&data->error, ERROR_FATAL, 0, "Can't open AAC file: %s", io_strerror(data->stream)); return data; } } /* find a frame */ if (buffer_fill_frame(data) <= 0) { decoder_error (&data->error, ERROR_FATAL, 0, "Not a valid (or unsupported) AAC file"); return data; } /* in case of a bug, make sure there is at least some data * in the buffer for NeAACDecInit() to work with. */ if (buffer_fill_min(data, 256) <= 0) { logit ("not enough data"); decoder_error (&data->error, ERROR_FATAL, 0, "AAC file/stream too short"); return data; } /* init decoder, returns the length of the header (if any) */ n = NeAACDecInit (data->decoder, buffer_data(data), buffer_length(data), &data->sample_rate, &data->channels); if (n < 0) { logit ("NeAACDecInit failed"); decoder_error (&data->error, ERROR_FATAL, 0, "libfaad can't open this stream"); return data; } logit ("sample rate %uHz, channels %d\n", (unsigned)data->sample_rate, (int)data->channels); if (!data->sample_rate || !data->channels) { decoder_error (&data->error, ERROR_FATAL, 0, "Invalid AAC sound parameters"); return data; } /* skip the header */ logit ("skipping header (%d bytes)\n", n); buffer_consume (data, n); /*NeAACDecInitDRM(data->decoder, data->sample_rate, data->channels);*/ if (fname) { data->duration = aac_count_time (data); if (data->duration > 0) { data->avg_bitrate = io_file_size (data->stream) / data->duration * 8; } else data->avg_bitrate = -1; } data->ok = 1; return data; }