int alogg_play_ex_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan, int speed, int loop) { int samples; /* continue only if we are not already playing it */ if (alogg_is_playing_ogg(ogg)) return ALOGG_OK; /* check the buffer is big enough*/ if (buffer_len < 4096) return ALOGG_PLAY_BUFFERTOOSMALL; /* create a new audiostream and play it */ samples = buffer_len / (ogg->stereo ? 2 : 1) / 2; /* / 2 = 16 bits samples */ ogg->audiostream = play_audio_stream(samples, 16, ogg->stereo, ogg->freq, vol, pan); ogg->audiostream_buffer_len = samples * (ogg->stereo ? 2 : 1) * 2; /* * 2 = 16 bits samples */ if (speed != 1000) adjust_sample(ogg->audiostream->samp, vol, pan, speed, TRUE); ogg->loop = loop; ogg->wait_for_audio_stop = 0; /* if the user asked for autopolling, install the interrupt now */ if (ogg->auto_polling) { LOCK_FUNCTION(alogg_autopoll_ogg); install_param_int(&alogg_autopoll_ogg, (void *)ogg, ogg->auto_poll_speed); } return ALOGG_OK; }
void alogg_set_loop_ogg(ALOGG_OGG *ogg, int loop) { /* return if we are not playing */ if (!alogg_is_playing_ogg(ogg)) return; ogg->loop = loop; }
void alogg_adjust_ogg(ALOGG_OGG *ogg, int vol, int pan, int speed, int loop) { /* return if we are not playing */ if (!alogg_is_playing_ogg(ogg)) return; /* adjust the sample */ adjust_sample(ogg->audiostream->samp, vol, pan, speed, TRUE); ogg->loop = loop; }
void *alogg_get_output_wave_ogg(ALOGG_OGG *ogg, int *buffer_size) { /* return if we are not playing */ if (!alogg_is_playing_ogg(ogg)) return NULL; /* set the buffer_size */ *buffer_size = ogg->audiostream_buffer_len; /* return the current audiostream sample data */ return (ogg->audiostream->samp->data); }
void alogg_stop_autopoll_ogg(ALOGG_OGG *ogg) { /* return if we are already not auto polling */ if (!ogg->auto_polling) return; ogg->auto_polling = FALSE; /* only remove the interrupt if we were already playing */ /* otherwise, stop will do*/ if (alogg_is_playing_ogg(ogg)) remove_param_int(&alogg_autopoll_ogg, (void *)ogg); }
void alogg_stop_ogg(ALOGG_OGG *ogg) { /* continue if we are playing it */ if (!alogg_is_playing_ogg(ogg)) return; /* remove the interrupt, if we were using autopolling */ if (ogg->auto_polling) remove_param_int(&alogg_autopoll_ogg, (void *)ogg); /* stop the audio stream */ stop_audio_stream(ogg->audiostream); ogg->audiostream = NULL; }
void alogg_start_autopoll_ogg(ALOGG_OGG *ogg, int speed) { /* return if we are already auto polling */ if (ogg->auto_polling) return; ogg->auto_polling = TRUE; ogg->auto_poll_speed = speed; /* only install the interrupt if we are already playing */ /* otherwise, play will do */ if (alogg_is_playing_ogg(ogg)) { LOCK_FUNCTION(alogg_autopoll_ogg); install_param_int(&alogg_autopoll_ogg, (void *)ogg, ogg->auto_poll_speed); } }
int get_pos_ms() { // Unfortunately the alogg_get_pos_msecs function // returns the ms offset that was last decoded, so it's always // ahead of the actual playback. Therefore we have this // hideous hack below to sort it out. if ((done) || (!alogg_is_playing_ogg(tune))) return 0; AUDIOSTREAM *str = alogg_get_audiostream_ogg(tune); long offs = (voice_get_position(str->voice) * 1000) / str->samp->freq; if (last_ms_offs != alogg_get_pos_msecs_ogg(tune)) { last_but_one_but_one = last_but_one; last_but_one = last_ms_offs; last_ms_offs = alogg_get_pos_msecs_ogg(tune); } // just about to switch buffers if (offs < 0) return last_but_one; int end_of_stream = alogg_is_end_of_ogg(tune); if ((str->active == 1) && (last_but_one_but_one > 0) && (str->locked == NULL)) { switch (end_of_stream) { case 0: case 2: offs -= (last_but_one - last_but_one_but_one); break; case 1: offs -= (last_but_one - last_but_one_but_one); break; } } /* char tbuffer[260]; sprintf(tbuffer,"offs: %d last_but_one_but_one: %d last_but_one: %d active:%d locked: %p EOS: %d", offs, last_but_one_but_one, last_but_one, str->active, str->locked, end_of_stream); write_log(tbuffer);*/ if (end_of_stream == 1) { return offs + last_but_one + extraOffset; } return offs + last_but_one_but_one + extraOffset; }
int alogg_is_looping_ogg(ALOGG_OGG *ogg) { if (!alogg_is_playing_ogg(ogg)) return FALSE; return ogg->loop; }
int alogg_poll_ogg(ALOGG_OGG *ogg) { void *audiobuf; char *audiobuf_p; int i, size_done; /* continue only if we are playing it */ if (!alogg_is_playing_ogg(ogg)) return ALOGG_POLL_NOTPLAYING; /* get the audio stream buffer and only continue if we need to fill it */ audiobuf = get_audio_stream_buffer(ogg->audiostream); if (audiobuf == NULL) return ALOGG_OK; /* clear the buffer with 16bit unsigned data */ { int i; unsigned short *j = (unsigned short *)audiobuf; for (i = 0; i < (ogg->audiostream_buffer_len / 2); i++, j++) *j = 0x8000; } /* if we need to fill it, but we were just waiting for it to finish */ if (!ogg->loop) { if (ogg->wait_for_audio_stop > 0) { free_audio_stream_buffer(ogg->audiostream); if (--ogg->wait_for_audio_stop == 0) { /* stop it */ //rest(500); alogg_stop_ogg(ogg); return ALOGG_POLL_PLAYJUSTFINISHED; } else return ALOGG_OK; } } audiobuf_p = (char *)audiobuf; size_done = 0; for (i = ogg->audiostream_buffer_len; i > 0; i -= size_done) { /* decode */ size_done = ov_read(&(ogg->vf), audiobuf_p, i, 0, 2, 0, &(ogg->current_section)); /* check if the decoding was not successful */ if (size_done < 0) { if (size_done == OV_HOLE) size_done = 0; else { free_audio_stream_buffer(ogg->audiostream); alogg_stop_ogg(ogg); alogg_rewind_ogg(ogg); return ALOGG_POLL_FRAMECORRUPT; } } else if (size_done == 0) { /* we have reached the end */ alogg_rewind_ogg(ogg); if (!ogg->loop) { free_audio_stream_buffer(ogg->audiostream); ogg->wait_for_audio_stop = 2; return ALOGG_OK; } } audiobuf_p += size_done; } /* lock the buffer */ free_audio_stream_buffer(ogg->audiostream); return ALOGG_OK; }
int alogg_poll_ogg_ts(ALOGG_OGG *ogg) { void *audiobuf; char *audiobuf_p; unsigned short *audiobuf_sp; int i, size_done, finished = 0; /* continue only if we are playing it */ if (!alogg_is_playing_ogg(ogg)) return ALOGG_POLL_NOTPLAYING; /* get the audio stream buffer and only continue if we need to fill it */ audiobuf = get_audio_stream_buffer(ogg->audiostream); if (audiobuf == NULL) return ALOGG_OK; /* clear the buffer with 16bit unsigned data */ { int i; unsigned short *j = (unsigned short *)audiobuf; for (i = 0; i < (ogg->audiostream_buffer_len / 2); i++, j++) *j = 0x8000; } /* if we need to fill it, but we were just waiting for it to finish */ if (!ogg->loop) { if (ogg->wait_for_audio_stop > 0) { free_audio_stream_buffer(ogg->audiostream); if (--ogg->wait_for_audio_stop == 0) { /* stop it */ alogg_stop_ogg(ogg); return ALOGG_POLL_PLAYJUSTFINISHED; } else return ALOGG_OK; } } audiobuf_sp = (unsigned short *)audiobuf; while (!finished && rubberband_available(ogg->time_stretch_state) < ogg->time_stretch_buffer_samples) { /* reset these each iteration so we don't overrun the buffer */ audiobuf_p = (char *)audiobuf; size_done = 0; /* read samples from Ogg Vorbis file */ for (i = ogg->audiostream_buffer_len; i > 0; i -= size_done) { /* decode */ size_done = ov_read(&(ogg->vf), audiobuf_p, i, alogg_endianess, 2, 0, &(ogg->current_section)); /* check if the decoding was not successful */ if (size_done < 0) { if (size_done == OV_HOLE) size_done = 0; else { free_audio_stream_buffer(ogg->audiostream); alogg_stop_ogg(ogg); alogg_rewind_ogg(ogg); return ALOGG_POLL_FRAMECORRUPT; } } else if (size_done == 0) { alogg_rewind_ogg(ogg); ogg->wait_for_audio_stop = 2; finished = 1; break; // playback finished so get out of loop } audiobuf_p += size_done; } /* process samples with Rubber Band */ if (ogg->stereo) { for (i = 0; i < ogg->time_stretch_buffer_samples; i++) { ogg->time_stretch_buffer[0][i] = (float)((long)audiobuf_sp[i * 2] - 0x8000) / (float)0x8000; //Convert sample to signed floating point format ogg->time_stretch_buffer[1][i] = (float)((long)audiobuf_sp[i * 2 + 1] - 0x8000) / (float)0x8000; //Repeat for the other channel's sample } } else { for (i = 0; i < ogg->time_stretch_buffer_samples; i++) { ogg->time_stretch_buffer[0][i] = (float)((long)audiobuf_sp[i] - 0x8000) / (float)0x8000; //Convert sample to signed floating point format } } rubberband_process(ogg->time_stretch_state, (const float **)ogg->time_stretch_buffer, ogg->time_stretch_buffer_samples, 0); } /* retrieve audio from rubberband and put it into stream buffer */ size_done = rubberband_retrieve(ogg->time_stretch_state, ogg->time_stretch_buffer, ogg->time_stretch_buffer_samples); if (ogg->stereo) { for (i = 0; i < size_done; i++) { if(ogg->time_stretch_buffer[0][i] > 1.0) { audiobuf_sp[i * 2] = 0xFFFF; } else if(ogg->time_stretch_buffer[0][i] < -1.0) { audiobuf_sp[i * 2] = 0; } else { audiobuf_sp[i * 2] = (ogg->time_stretch_buffer[0][i] * (float)0x8000) + (float)0x8000; //Convert sample back to unsigned integer format } if(ogg->time_stretch_buffer[1][i] > 1.0) { audiobuf_sp[i * 2 + 1] = 0xFFFF; } else if(ogg->time_stretch_buffer[1][i] < -1.0) { audiobuf_sp[i * 2 + 1] = 0; } else { audiobuf_sp[i * 2 + 1] = (ogg->time_stretch_buffer[1][i] * (float)0x8000) + (float)0x8000; //Repeat for the other channel's sample } } } else { for (i = 0; i < size_done; i++) { if(ogg->time_stretch_buffer[0][i] > 1.0) { audiobuf_sp[i] = 0xFFFF; } else if(ogg->time_stretch_buffer[0][i] < -1.0) { audiobuf_sp[i] = 0; } else { audiobuf_sp[i] = (ogg->time_stretch_buffer[0][i] * (float)0x8000) + (float)0x8000; //Convert sample back to unsigned integer format } } } /* lock the buffer */ if(alogg_buffer_callback) { alogg_buffer_callback(audiobuf, ogg->audiostream_buffer_len); } free_audio_stream_buffer(ogg->audiostream); return ALOGG_OK; }