GLdc/samples/dreamroq/libdcmc/snddrv.c
2023-08-22 18:56:30 -04:00

143 lines
3.5 KiB
C

/*
**
** (C) Josh 'PH3NOM' Pearson 2011
**
*/
/*
** To anyone looking at this code:
**
** This driver runs in its own thread on the sh4.
**
** When the AICA driver requests more samples,
** it will signal sndbuf_status=SNDDRV_STATUS_NEEDBUF
** and assign the number of requested samples to snddrv.pcm_needed.
**
** The decoders need to check sndbuf_status,
** when more samples are requested by the driver ** the decoders will loop
** decoding into pcm_buffer untill pcm_bytes==snddrv.pcm_needed
** at that point the decoder signals sndbuf_status=SNDDRV_STATUS_HAVEBUF
**
*/
#include <kos/thread.h>
#include <dc/sound/stream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "snddrv.h"
snd_stream_hnd_t shnd;
kthread_t * snddrv_thd;
static int snddrv_vol = 255;
snd_drv snddrv;
/* Increase the Sound Driver volume */
int snddrv_volume_up() {
if( snddrv_vol <= 245 ) {
snddrv_vol += 10;
snd_stream_volume(shnd, snddrv_vol);
}
return snddrv_vol;
}
/* Decrease the Sound Driver volume */
int snddrv_volume_down() {
if( snddrv_vol >= 10 ) {
snddrv_vol -= 10;
snd_stream_volume(shnd, snddrv_vol);
}
return snddrv_vol;
}
/* Exit the Sound Driver */
int snddrv_exit() {
if( snddrv.drv_status != SNDDRV_STATUS_NULL ) {
snddrv.drv_status = SNDDRV_STATUS_DONE;
snddrv.buf_status = SNDDRV_STATUS_BUFEND;
while( snddrv.drv_status != SNDDRV_STATUS_NULL )
thd_pass();
printf("SNDDRV: Exited\n");
}
memset( snddrv.pcm_buffer, 0, 65536+16384);
snddrv.pcm_bytes = 0;
snddrv.pcm_needed = 0;
SNDDRV_FREE_STRUCT();
return snddrv.drv_status;
}
/* Signal how many samples the AICA needs, then wait for the deocder to produce them */
static void *snddrv_callback(snd_stream_hnd_t hnd, int len, int * actual) {
/* Signal the Decoder thread how many more samples are needed */
snddrv.pcm_needed = len;
snddrv.buf_status = SNDDRV_STATUS_NEEDBUF;
/* Wait for the samples to be ready */
while( snddrv.buf_status != SNDDRV_STATUS_HAVEBUF && snddrv.buf_status != SNDDRV_STATUS_BUFEND )
thd_pass();
snddrv.pcm_ptr = snddrv.pcm_buffer;
snddrv.pcm_bytes = 0;
*actual = len;
return snddrv.pcm_ptr;
}
static int snddrv_thread() {
printf("SNDDRV: Rate - %i, Channels - %i\n", snddrv.rate, snddrv.channels);
shnd = snd_stream_alloc(snddrv_callback, SND_STREAM_BUFFER_MAX/4);
snd_stream_start(shnd, snddrv.rate, snddrv.channels-1);
snddrv.drv_status = SNDDRV_STATUS_STREAMING;
while( snddrv.drv_status != SNDDRV_STATUS_DONE && snddrv.drv_status != SNDDRV_STATUS_ERROR ) {
snd_stream_poll(shnd);
thd_sleep(20);
}
snddrv.drv_status = SNDDRV_STATUS_NULL;
snd_stream_destroy(shnd);
snd_stream_shutdown();
printf("SNDDRV: Finished\n");
return snddrv.drv_status;
}
/* Start the AICA Sound Stream Thread */
int snddrv_start( int rate, int chans ) {
snddrv.rate = rate;
snddrv.channels = chans;
if( snddrv.channels > 2) {
printf("SNDDRV: ERROR - Exceeds maximum channels\n");
return -1;
}
printf("SNDDRV: Creating Driver Thread\n");
snddrv.drv_status = SNDDRV_STATUS_INITIALIZING;
snd_stream_init();
/*libdcmc/snddrv.c:136: warning: passing arg 1 of `thd_create' from incompatible pointer type */ //Ian micheal 2020 warning
snddrv_thd = thd_create(0, snddrv_thread, NULL );
return snddrv.drv_status;
}