Skip to content

Commit

Permalink
Fixed binary compatibility, added Sound_GetDuration().
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed May 12, 2004
1 parent 65dc67d commit ef8cebc
Show file tree
Hide file tree
Showing 18 changed files with 89 additions and 50 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG
Expand Up @@ -2,7 +2,9 @@
* CHANGELOG.
*/


05112004 - Added Sound_GetDuration() and moved total_time out of Sound_Sample
struct and into it's opaque data...this fixes binary compatibility
with apps written for SDL_sound 1.0.
05082004 - Started 1.1.0 development branch with code to determine the total
length of a sample (thanks to Wesley, Eric, Wang, and Ahilan!)...
this patch was originally committed to CVS on 10252003, but it is
Expand Down
7 changes: 7 additions & 0 deletions SDL_sound.c
Expand Up @@ -901,5 +901,12 @@ int Sound_Seek(Sound_Sample *sample, Uint32 ms)
} /* Sound_Rewind */


Sint32 Sound_GetDuration(Sound_Sample *sample)
{
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, -1);
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
return(internal->total_time);
} /* Sound_GetDuration */

/* end of SDL_sound.c ... */

26 changes: 25 additions & 1 deletion SDL_sound.h
Expand Up @@ -185,7 +185,6 @@ typedef struct
void *buffer; /**< Decoded sound data lands in here. */
Uint32 buffer_size; /**< Current size of (buffer), in bytes (Uint8). */
Sound_SampleFlags flags; /**< Flags relating to this sample. */
Sint32 total_time; /**< Total length of song or track */
} Sound_Sample;


Expand Down Expand Up @@ -500,6 +499,31 @@ SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSampleFromFile(const char *fname,
SNDDECLSPEC void SDLCALL Sound_FreeSample(Sound_Sample *sample);


/**
* \fn Sint32 Sound_GetDuration(Sound_Sample *sample)
* \brief Retrieve total play time of sample, in milliseconds.
*
* Report total time length of sample, in milliseconds. This is a fast
* call. Duration is calculated during Sound_NewSample*, so this is just
* an accessor into otherwise opaque data.
*
* Please note that not all formats can determine a total time, some can't
* be exact without fully decoding the data, and thus will estimate the
* duration. Many decoders will require the ability to seek in the data
* stream to calculate this, so even if we can tell you how long an .ogg
* file will be, the same data set may fail if it's, say, streamed over an
* HTTP connection. Plan accordingly.
*
* Most people won't need this function to just decode and playback, but it
* can be useful for informational purposes in, say, a music player's UI.
*
* \param sample Sound_Sample from which to retrieve duration information.
* \return Sample length in milliseconds, or -1 if duration can't be
* determined for any reason.
*/
SNDDECLSPEC Sint32 SDLCALL Sound_GetDuration(Sound_Sample *sample);


/**
* \fn int Sound_SetBufferSize(Sound_Sample *sample, Uint32 new_size)
* \brief Change the current buffer size for a sample.
Expand Down
1 change: 1 addition & 0 deletions SDL_sound_internal.h
Expand Up @@ -255,6 +255,7 @@ typedef struct __SOUND_SAMPLEINTERNAL__
void *buffer;
Uint32 buffer_size;
void *decoder_private;
Sint32 total_time;
} Sound_SampleInternal;


Expand Down
6 changes: 3 additions & 3 deletions decoders/aiff.c
Expand Up @@ -477,9 +477,9 @@ static int AIFF_open(Sound_Sample *sample, const char *ext)
sample->actual.rate = c.sampleRate;

/* Really, sample->total_time = (c.numSampleFrames*1000) c.sampleRate */
sample->total_time = (c.numSampleFrames / c.sampleRate) * 1000;
sample->total_time += (c.numSampleFrames % c.sampleRate)
* 1000 / c.sampleRate;
internal->total_time = (c.numSampleFrames / c.sampleRate) * 1000;
internal->total_time += (c.numSampleFrames % c.sampleRate)
* 1000 / c.sampleRate;

if (c.sampleSize <= 8)
{
Expand Down
8 changes: 4 additions & 4 deletions decoders/au.c
Expand Up @@ -246,10 +246,10 @@ static int AU_open(Sound_Sample *sample, const char *ext)

bytes_per_second = ( ( dec->encoding == AU_ENC_LINEAR_16 ) ? 2 : 1 )
* sample->actual.rate * sample->actual.channels ;
sample->total_time = ((dec->remaining == -1) ? (-1) :
( ( dec->remaining / bytes_per_second ) * 1000 ) +
( ( dec->remaining % bytes_per_second ) * 1000 /
bytes_per_second ) );
internal->total_time = ((dec->remaining == -1) ? (-1) :
( ( dec->remaining / bytes_per_second ) * 1000 ) +
( ( dec->remaining % bytes_per_second ) * 1000 /
bytes_per_second ) );

sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
dec->total = dec->remaining;
Expand Down
25 changes: 15 additions & 10 deletions decoders/flac.c
Expand Up @@ -233,6 +233,8 @@ static void metadata_callback(
void *client_data)
{
flac_t *f = (flac_t *) client_data;
Sound_Sample *sample = f->sample;
Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;

SNDDBG(("FLAC: Metadata callback.\n"));

Expand All @@ -244,24 +246,27 @@ static void metadata_callback(
SNDDBG(("FLAC: Metadata is streaminfo.\n"));

f->is_flac = 1;
f->sample->actual.channels = metadata->data.stream_info.channels;
f->sample->actual.rate = metadata->data.stream_info.sample_rate;
sample->actual.channels = metadata->data.stream_info.channels;
sample->actual.rate = metadata->data.stream_info.sample_rate;

if (metadata->data.stream_info.sample_rate == 0 ||
if (metadata->data.stream_info.sample_rate == 0 ||
metadata->data.stream_info.total_samples == 0)
f->sample->total_time = -1;
else {
f->sample->total_time = (metadata->data.stream_info.total_samples)
{
internal->total_time = -1;
} /* if */
else
{
internal->total_time = (metadata->data.stream_info.total_samples)
/ metadata->data.stream_info.sample_rate * 1000;
f->sample->total_time += (metadata->data.stream_info.total_samples
internal->total_time += (metadata->data.stream_info.total_samples
% metadata->data.stream_info.sample_rate) * 1000
/ metadata->data.stream_info.sample_rate;
}
} /* else */

if (metadata->data.stream_info.bits_per_sample > 8)
f->sample->actual.format = AUDIO_S16MSB;
sample->actual.format = AUDIO_S16MSB;
else
f->sample->actual.format = AUDIO_S8;
sample->actual.format = AUDIO_S8;
} /* if */
} /* metadata_callback */

Expand Down
4 changes: 2 additions & 2 deletions decoders/midi.c
Expand Up @@ -107,13 +107,13 @@ static int MIDI_open(Sound_Sample *sample, const char *ext)
SNDDBG(("MIDI: Accepting data stream.\n"));

internal->decoder_private = (void *) song;
internal->total_time = Timidity_GetSongLength(song);

sample->actual.channels = 2;
sample->actual.rate = 44100;
sample->actual.format = AUDIO_S16SYS;

sample->total_time = Timidity_GetSongLength(song);
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;

return(1); /* we'll handle this data. */
} /* MIDI_open */

Expand Down
10 changes: 5 additions & 5 deletions decoders/mikmod.c
Expand Up @@ -282,9 +282,9 @@ static int MIKMOD_open(Sound_Sample *sample, const char *ext)

/*
* module->sngtime = current song time in 2^-10 seconds
* sample->total_time = (module->sngtime * 1000) / (1<<10)
* internal->total_time = (module->sngtime * 1000) / (1<<10)
*/
sample->total_time = (module->sngtime * 1000) / (1<<10);
internal->total_time = (module->sngtime * 1000) / (1<<10);

SNDDBG(("MIKMOD: Name: %s\n", module->songname));
SNDDBG(("MIKMOD: Type: %s\n", module->modtype));
Expand Down Expand Up @@ -322,7 +322,7 @@ static int MIKMOD_open(Sound_Sample *sample, const char *ext)
* For each position (which corresponds to a particular pattern),
* get the speed values and compute the time length of the segment
*/
sample->total_time = 0;
internal->total_time = 0;
for (i = 0; i < module->numpos; i++)
{
Player_SetPosition(i);
Expand Down Expand Up @@ -378,7 +378,7 @@ static int MIKMOD_open(Sound_Sample *sample, const char *ext)
125.0 / module->bpm);
} /* for */
/* Now convert to milliseconds and store the value */
sample->total_time = (Sint32)(segment_time * 1000);
internal->total_time = (Sint32)(segment_time * 1000);

/* Reset the sample to the beginning */
Player_SetPosition(0);
Expand Down Expand Up @@ -462,7 +462,7 @@ static int MIKMOD_seek(Sound_Sample *sample, Uint32 ms)
return(1);
} /* if */

if (ms >= sample->total_time)
if (ms >= internal->total_time)
Player_SetPosition(module->numpos);

/* Convert time to seconds (double) to make comparisons easier */
Expand Down
2 changes: 1 addition & 1 deletion decoders/modplug.c
Expand Up @@ -270,7 +270,7 @@ static int MODPLUG_open(Sound_Sample *sample, const char *ext)
if (modplug_mutex != NULL)
SDL_UnlockMutex(modplug_mutex);

sample->total_time = ModPlug_GetLength(module);
internal->total_time = ModPlug_GetLength(module);
SNDDBG(("MODPLUG: [%d ms] %s\n",
ModPlug_GetLength(module), ModPlug_GetName(module)));

Expand Down
4 changes: 2 additions & 2 deletions decoders/mpglib.c
Expand Up @@ -197,8 +197,8 @@ static int MPGLIB_open(Sound_Sample *sample, const char *ext)
if (SDL_RWseek(internal->rw, pos, SEEK_SET) != pos) {
BAIL_MACRO("MPGLIB: Cannot go back to save spot in file.", 0);
}
sample->total_time = total_byte_size / mpg->mp.fr.bitrate * 8.0;
sample->total_time += (total_byte_size % mpg->mp.fr.bitrate) * 8.0
internal->total_time = total_byte_size / mpg->mp.fr.bitrate * 8.0;
internal->total_time += (total_byte_size % mpg->mp.fr.bitrate) * 8.0
/ mpg->mp.fr.bitrate;
}

Expand Down
4 changes: 2 additions & 2 deletions decoders/ogg.c
Expand Up @@ -212,9 +212,9 @@ static int OGG_open(Sound_Sample *sample, const char *ext)
sample->actual.channels = (Uint8) info->channels;
total_time = ov_time_total(vf, -1);
if (OV_EINVAL == total_time)
sample->total_time = -1;
internal->total_time = -1;
else
sample->total_time = (Sint32)(total_time * 1000.0 + 0.5);
internal->total_time = (Sint32)(total_time * 1000.0 + 0.5);


/*
Expand Down
2 changes: 1 addition & 1 deletion decoders/quicktime.c
Expand Up @@ -547,7 +547,7 @@ static int QT_open(Sound_Sample *sample, const char *ext)
instance = QT_open_internal(sample, ext);
internal->decoder_private = (void*)instance;

sample->total_time = -1; /* return -1 for total time of song for now */
internal->total_time = -1; /* return -1 for total time of song for now */

return(instance != NULL);

Expand Down
4 changes: 2 additions & 2 deletions decoders/raw.c
Expand Up @@ -135,8 +135,8 @@ static int RAW_open(Sound_Sample *sample, const char *ext)

sample_rate = (sample->actual.rate * sample->actual.channels
* ( (sample->actual.format & 0x0018) >> 3) );
sample->total_time = ( pos ) / sample_rate * 1000;
sample->total_time += (pos % sample_rate) * 1000 / sample_rate;
internal->total_time = ( pos ) / sample_rate * 1000;
internal->total_time += (pos % sample_rate) * 1000 / sample_rate;

return(1); /* we'll handle this data. */
} /* RAW_open */
Expand Down
4 changes: 2 additions & 2 deletions decoders/shn.c
Expand Up @@ -580,8 +580,8 @@ static __inline__ int parse_riff_header(shn_t *shn, Sound_Sample *sample)
BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* 'data' header */
BAIL_IF_MACRO(u32 != dataID, "SHN: No 'data' header.", 0);
BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* chunksize */
sample->total_time = u32 / bytes_per_second * 1000;
sample->total_time += (u32 % bytes_per_second) * 1000 / bytes_per_second;
internal->total_time = u32 / bytes_per_second * 1000;
internal->total_time += (u32 % bytes_per_second) * 1000 / bytes_per_second;
return(1);
} /* parse_riff_header */

Expand Down
2 changes: 1 addition & 1 deletion decoders/smpeg.c
Expand Up @@ -212,7 +212,7 @@ static int _SMPEG_open(Sound_Sample *sample, const char *ext)
sample->actual.rate = spec.freq;
sample->actual.channels = spec.channels;
sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
sample->total_time = smpeg_info.total_time * 1000;
internal->total_time = smpeg_info.total_time * 1000;
internal->decoder_private = smpeg;

SMPEG_play(smpeg);
Expand Down
20 changes: 10 additions & 10 deletions decoders/voc.c
Expand Up @@ -245,9 +245,9 @@ static int voc_get_block(Sound_Sample *sample, vs_t *v)

bytes_per_second = sample->actual.rate
* sample->actual.channels;
sample->total_time += ( v->rest ) / bytes_per_second * 1000;
sample->total_time += (v->rest % bytes_per_second) * 1000
/ bytes_per_second;
internal->total_time += ( v->rest ) / bytes_per_second * 1000;
internal->total_time += (v->rest % bytes_per_second) * 1000
/ bytes_per_second;
return 1;

case VOC_DATA_16:
Expand Down Expand Up @@ -281,11 +281,11 @@ static int voc_get_block(Sound_Sample *sample, vs_t *v)
return 0;
v->rest = sblen - 12;

bytes_per_second = ((v->size == ST_SIZE_WORD) ? (2) : (1)) *
sample->actual.rate * v->channels;
sample->total_time += v->rest / bytes_per_second * 1000;
sample->total_time += ( v->rest % bytes_per_second ) * 1000
/ bytes_per_second;
bytes_per_second = ((v->size == ST_SIZE_WORD) ? (2) : (1)) *
sample->actual.rate * v->channels;
internal->total_time += v->rest / bytes_per_second * 1000;
internal->total_time += ( v->rest % bytes_per_second ) * 1000
/ bytes_per_second;
return 1;

case VOC_CONT:
Expand Down Expand Up @@ -315,8 +315,8 @@ static int voc_get_block(Sound_Sample *sample, vs_t *v)
v->rest = period;
v->silent = 1;

sample->total_time += (period) / (v->rate) * 1000;
sample->total_time += (period % v->rate) * 1000 / v->rate;
internal->total_time += (period) / (v->rate) * 1000;
internal->total_time += (period % v->rate) * 1000 / v->rate;
return 1;

case VOC_LOOP:
Expand Down
6 changes: 3 additions & 3 deletions decoders/wav.c
Expand Up @@ -724,9 +724,9 @@ static int WAV_open_internal(Sound_Sample *sample, const char *ext, fmt_t *fmt)
sample->actual.channels );
internal->decoder_private = (void *) w;

sample->total_time = (fmt->total_bytes / fmt->dwAvgBytesPerSec) * 1000;
sample->total_time += (fmt->total_bytes % fmt->dwAvgBytesPerSec)
* 1000 / fmt->dwAvgBytesPerSec;
internal->total_time = (fmt->total_bytes / fmt->dwAvgBytesPerSec) * 1000;
internal->total_time += (fmt->total_bytes % fmt->dwAvgBytesPerSec)
* 1000 / fmt->dwAvgBytesPerSec;

sample->flags = SOUND_SAMPLEFLAG_NONE;
if (fmt->seek_sample != NULL)
Expand Down

0 comments on commit ef8cebc

Please sign in to comment.