rockbox/apps/codecs/dumb/src/allegro/alplay.c

271 lines
5.4 KiB
C
Raw Normal View History

/* _______ ____ __ ___ ___
* \ _ \ \ / \ / \ \ / / ' ' '
* | | \ \ | | || | \/ | . .
* | | | | | | || ||\ /| |
* | | | | | | || || \/ | | ' ' '
* | | | | | | || || | | . .
* | |_/ / \ \__// || | |
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
* / \
* / . \
* alplay.c - Functions to play a DUH through / / \ \
* an Allegro audio stream. | < / \_
* | \/ /\ /
* By entheh. \_ / > /
* | \ / /
* | ' /
* \__/
*/
#include <stdlib.h>
#include <allegro.h>
#include "aldumb.h"
#define ADP_PLAYING 1
struct AL_DUH_PLAYER
{
int flags;
long bufsize;
int freq;
AUDIOSTREAM *stream;
DUH_SIGRENDERER *sigrenderer; /* If this is NULL, stream is invalid. */
float volume;
int silentcount;
};
AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq)
{
AL_DUH_PLAYER *dp;
/* This restriction is imposed by Allegro. */
ASSERT(n_channels > 0);
ASSERT(n_channels <= 2);
if (!duh)
return NULL;
dp = malloc(sizeof(*dp));
if (!dp)
return NULL;
dp->flags = ADP_PLAYING;
dp->bufsize = bufsize;
dp->freq = freq;
dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128);
if (!dp->stream) {
free(dp);
return NULL;
}
voice_set_priority(dp->stream->voice, 255);
dp->sigrenderer = duh_start_sigrenderer(duh, 0, n_channels, pos);
if (!dp->sigrenderer) {
stop_audio_stream(dp->stream);
free(dp);
return NULL;
}
dp->volume = volume;
dp->silentcount = 0;
return dp;
}
void al_stop_duh(AL_DUH_PLAYER *dp)
{
if (dp) {
if (dp->sigrenderer) {
duh_end_sigrenderer(dp->sigrenderer);
stop_audio_stream(dp->stream);
}
free(dp);
}
}
void al_pause_duh(AL_DUH_PLAYER *dp)
{
if (dp && dp->sigrenderer && (dp->flags & ADP_PLAYING)) {
voice_stop(dp->stream->voice);
dp->flags &= ~ADP_PLAYING;
}
}
void al_resume_duh(AL_DUH_PLAYER *dp)
{
if (dp && dp->sigrenderer && !(dp->flags & ADP_PLAYING)) {
voice_start(dp->stream->voice);
dp->flags |= ADP_PLAYING;
}
}
void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority)
{
if (dp && dp->sigrenderer)
voice_set_priority(dp->stream->voice, priority);
}
void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume)
{
if (dp)
dp->volume = volume;
}
int al_poll_duh(AL_DUH_PLAYER *dp)
{
unsigned short *sptr;
long n;
long size;
int n_channels;
if (!dp || !dp->sigrenderer)
return 1;
if (!(dp->flags & ADP_PLAYING))
return 0;
sptr = get_audio_stream_buffer(dp->stream);
if (!sptr)
return 0;
n = duh_render(dp->sigrenderer, 16, 1, dp->volume, 65536.0 / dp->freq, dp->bufsize, sptr);
if (n == 0) {
if (++dp->silentcount >= 2) {
duh_end_sigrenderer(dp->sigrenderer);
free_audio_stream_buffer(dp->stream);
stop_audio_stream(dp->stream);
dp->sigrenderer = NULL;
return 1;
}
}
n_channels = duh_sigrenderer_get_n_channels(dp->sigrenderer);
n *= n_channels;
size = dp->bufsize * n_channels;
for (; n < size; n++)
sptr[n] = 0x8000;
free_audio_stream_buffer(dp->stream);
return 0;
}
long al_duh_get_position(AL_DUH_PLAYER *dp)
{
return dp ? duh_sigrenderer_get_position(dp->sigrenderer) : -1;
}
AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq)
{
AL_DUH_PLAYER *dp;
int n_channels;
if (!sigrenderer)
return NULL;
dp = malloc(sizeof(*dp));
if (!dp)
return NULL;
n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
/* This restriction is imposed by Allegro. */
ASSERT(n_channels > 0);
ASSERT(n_channels <= 2);
dp->flags = ADP_PLAYING;
dp->bufsize = bufsize;
dp->freq = freq;
dp->stream = play_audio_stream(bufsize, 16, n_channels - 1, freq, 255, 128);
if (!dp->stream) {
free(dp);
return NULL;
}
voice_set_priority(dp->stream->voice, 255);
dp->sigrenderer = sigrenderer;
dp->volume = volume;
dp->silentcount = 0;
return dp;
}
DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp)
{
return dp ? dp->sigrenderer : NULL;
}
/* IMPORTANT: This function will return NULL if the music has ended. */
// Should this be changed? User might want to hack the underlying SIGRENDERER
// and resurrect it (e.g. change pattern number), before it gets destroyed...
DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp)
{
if (dp) {
DUH_SIGRENDERER *sigrenderer = dp->sigrenderer;
if (sigrenderer) stop_audio_stream(dp->stream);
free(dp);
return sigrenderer;
}
return NULL;
}
/* DEPRECATED */
AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq)
{
return al_duh_encapsulate_sigrenderer(dr, volume, bufsize, freq);
}
/* DEPRECATED */
DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp)
{
return al_duh_get_sigrenderer(dp);
}
/* DEPRECATED */
DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp)
{
return al_duh_decompose_to_sigrenderer(dp);
}