static struct mp3_data *mp3_open_internal (const char *file, const int buffered) { struct mp3_data *data; data = (struct mp3_data *)xmalloc (sizeof(struct mp3_data)); data->ok = 0; decoder_error_init (&data->error); /* Reset information about the file */ data->freq = 0; data->channels = 0; data->skip_frames = 0; data->bitrate = -1; data->avg_bitrate = -1; /* Open the file */ data->io_stream = io_open (file, buffered); if (io_ok(data->io_stream)) { data->ok = 1; data->size = io_file_size (data->io_stream); mad_stream_init (&data->stream); mad_frame_init (&data->frame); mad_synth_init (&data->synth); if (options_get_int("Mp3IgnoreCRCErrors")) mad_stream_options (&data->stream, MAD_OPTION_IGNORECRC); data->duration = count_time_internal (data); mad_frame_mute (&data->frame); data->stream.next_frame = NULL; data->stream.sync = 0; data->stream.error = MAD_ERROR_NONE; if (io_seek(data->io_stream, SEEK_SET, 0) == (off_t)-1) { decoder_error (&data->error, ERROR_FATAL, 0, "seek failed"); io_close (data->io_stream); mad_stream_finish (&data->stream); mad_frame_finish (&data->frame); mad_synth_finish (&data->synth); data->ok = 0; } data->stream.error = MAD_ERROR_BUFLEN; } else { decoder_error (&data->error, ERROR_FATAL, 0, "Can't open: %s", io_strerror(data->io_stream)); io_close (data->io_stream); } return data; }
/* This should be called with a unique decoder instance as the seeking * it does triggers an FAAD bug which results in distorted audio due to * retained state being corrupted. (One suspects NeAACDecPostSeekReset() * should resolve the problem but experimentation suggests not and no * documentation exists describing its use.) */ static int aac_count_time (struct aac_data *data) { NeAACDecFrameInfo frame_info; int samples = 0, bytes = 0, frames = 0; off_t file_size; int16_t *sample_buf; file_size = io_file_size (data->stream); if (file_size == -1) return -1; if (io_seek(data->stream, file_size / 2, SEEK_SET) == -1) return -1; buffer_flush (data); /* Guess track length by decoding the middle 50 frames which have * more than 25% of samples having absolute values greater than 16. */ while (frames < 50) { if (buffer_fill_frame (data) <= 0) break; sample_buf = NeAACDecDecode (data->decoder, &frame_info, buffer_data (data), buffer_length (data)); if (frame_info.error == 0 && frame_info.samples > 0) { unsigned int ix, zeroes = 0; for (ix = 0; ix < frame_info.samples; ix += 1) { if (RANGE(-16, sample_buf[ix], 16)) zeroes += 1; } if (zeroes * 4 < frame_info.samples) { samples += frame_info.samples; bytes += frame_info.bytesconsumed; frames += 1; } } if (frame_info.bytesconsumed == 0) break; buffer_consume (data, frame_info.bytesconsumed); } if (frames == 0) return -1; samples /= frames; samples /= data->channels; bytes /= frames; return ((file_size / bytes) * samples) / data->sample_rate; }
static int aac_count_time (struct aac_data *data) { NeAACDecFrameInfo frame_info; int samples = 0, bytes = 0, frames = 0; off_t file_size; char *sample_buf; long saved_pos; file_size = io_file_size (data->stream); if (file_size == -1) return -1; saved_pos = io_tell (data->stream); /* guess track length by decoding the first 10 frames */ while (frames < 10) { if (buffer_fill_frame(data) <= 0) break; sample_buf = NeAACDecDecode(data->decoder, &frame_info, buffer_data(data), buffer_length(data)); if (frame_info.error == 0 && frame_info.samples > 0) { samples += frame_info.samples; bytes += frame_info.bytesconsumed; frames++; } if (frame_info.bytesconsumed == 0) break; buffer_consume (data, frame_info.bytesconsumed); } if (io_seek(data->stream, saved_pos, SEEK_SET) == (off_t)-1) { logit ("Can't seek after couting time"); return -1; } if (frames == 0) return -1; samples /= frames; samples /= data->channels; bytes /= frames; return ((file_size / bytes) * samples) / data->sample_rate; }
static cibool asap_load(ASAP_Decoder *d, const char *filename) { struct io_stream *s; ssize_t module_len; unsigned char *module; cibool ok; const ASAPInfo *info; int song; int duration; d->asap = NULL; decoder_error_init(&d->error); s = io_open(filename, 0); if (s == NULL) { decoder_error(&d->error, ERROR_FATAL, 0, "Can't open %s", filename); return FALSE; } module_len = io_file_size(s); module = (unsigned char *) xmalloc(module_len); module_len = io_read(s, module, module_len); io_close(s); d->asap = ASAP_New(); if (d->asap == NULL) { decoder_error(&d->error, ERROR_FATAL, 0, "Out of memory"); return FALSE; } ok = ASAP_Load(d->asap, filename, module, module_len); free(module); if (!ok) { decoder_error(&d->error, ERROR_FATAL, 0, "Unsupported file format"); return FALSE; } info = ASAP_GetInfo(d->asap); song = ASAPInfo_GetDefaultSong(info); duration = ASAPInfo_GetDuration(info, song); if (duration < 0) duration = DEFAULT_SONG_LENGTH * 1000; d->duration = duration; return TRUE; }
static int count_time (struct spx_data *data) { unsigned long last_granulepos = 0; /* Seek to somewhere neer the last page */ if (io_file_size(data->stream) > 10000) { debug ("Seeking near the end"); if (io_seek(data->stream, -10000, SEEK_END) == -1) logit ("Seeking failed, scaning whole file"); ogg_sync_reset (&data->oy); } /* Read granulepos from the last packet */ while (!io_eof(data->stream)) { /* Sync to page and read it */ while (!io_eof(data->stream)) { char *buf; int nb_read; if (ogg_sync_pageout(&data->oy, &data->og) == 1) { debug ("Sync"); break; } else if (!io_eof(data->stream)) { debug ("Need more data"); buf = ogg_sync_buffer (&data->oy, 200); nb_read = io_read (data->stream, buf, 200); ogg_sync_wrote (&data->oy, nb_read); } } /* We have last packet */ if (io_eof(data->stream)) break; last_granulepos = ogg_page_granulepos (&data->og); } return last_granulepos / data->rate; }
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 int count_time (struct spx_data *data) { ogg_int64_t last_granulepos = 0; /* Seek to somewhere near the last page */ if (io_file_size(data->stream) > 10000) { debug ("Seeking near the end"); if (io_seek(data->stream, -10000, SEEK_END) == -1) logit ("Seeking failed, scanning whole file"); ogg_sync_reset (&data->oy); } /* Read granulepos from the last packet */ while (!io_eof(data->stream)) { /* Sync to page and read it */ while (!io_eof(data->stream)) { if (ogg_sync_pageout(&data->oy, &data->og) == 1) { debug ("Sync"); break; } if (!io_eof(data->stream)) { debug ("Need more data"); get_more_data (data); } } /* We have last packet */ if (io_eof(data->stream)) break; last_granulepos = ogg_page_granulepos (&data->og); } return last_granulepos / data->rate; }
static int spx_seek (void *prv_data, int sec) { struct spx_data *data = (struct spx_data *)prv_data; off_t begin = 0, end, old_pos; assert (sec >= 0); end = io_file_size (data->stream); if (end == -1) return -1; old_pos = io_tell (data->stream); debug ("Seek request to %ds", sec); while (1) { off_t middle = (end + begin) / 2; ogg_int64_t granule_pos; int position_seconds; debug ("Seek to %"PRId64, middle); if (io_seek(data->stream, middle, SEEK_SET) == -1) { io_seek (data->stream, old_pos, SEEK_SET); ogg_stream_reset (&data->os); ogg_sync_reset (&data->oy); return -1; } debug ("Syncing..."); /* Sync to page and read it */ ogg_sync_reset (&data->oy); while (!io_eof(data->stream)) { if (ogg_sync_pageout(&data->oy, &data->og) == 1) { debug ("Sync"); break; } if (!io_eof(data->stream)) { debug ("Need more data"); get_more_data (data); } } if (io_eof(data->stream)) { debug ("EOF when syncing"); return -1; } granule_pos = ogg_page_granulepos(&data->og); position_seconds = granule_pos / data->rate; debug ("We are at %ds", position_seconds); if (position_seconds == sec) { ogg_stream_pagein (&data->os, &data->og); debug ("We have it at granulepos %"PRId64, granule_pos); break; } else if (sec < position_seconds) { end = middle; debug ("going back"); } else { begin = middle; debug ("going forward"); } debug ("begin - end %"PRId64" - %"PRId64, begin, end); if (end - begin <= 200) { /* Can't find the exact position. */ sec = position_seconds; break; } } ogg_sync_reset (&data->oy); ogg_stream_reset (&data->os); return sec; }
get_comments (data, tags); if (tags_sel & TAGS_TIME) tags->time = count_time (data); } spx_close (data); } } static int spx_seek (void *prv_data ATTR_UNUSED, int sec) { struct spx_data *data = (struct spx_data *)prv_data; ssize_t begin = 0, end; size_t old_pos; end = io_file_size (data->stream); if (end == -1) return -1; old_pos = io_tell (data->stream); debug ("Seek request to %ds", sec); while (1) { ssize_t middle = (end + begin) / 2; size_t granule_pos; int position_seconds; debug ("Seek to %ld", (long)middle); if (io_seek(data->stream, middle, SEEK_SET) == -1) { io_seek (data->stream, old_pos, SEEK_SET);
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; }