1 /* wiisound.c: Wii sound routines
2    Copyright (c) 2008-2009 Bjoern Giesler, Philip Kendall
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation, Inc.,
16    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 
18 */
19 
20 #include <config.h>
21 
22 #include <string.h>
23 #include <unistd.h>
24 
25 #include "fuse.h"
26 #include "sfifo.h"
27 
28 #include <gccore.h>
29 #include <ogc/audio.h>
30 
31 #ifndef MIN
32 #define MIN(x,y) ((x) < (y) ? (x) : (y))
33 #endif
34 
35 int samplerate;
36 int streamstate;
37 sfifo_t sound_fifo;
38 
39 #define BUFSIZE 16384
40 u8 dmabuf[BUFSIZE<<1] ATTRIBUTE_ALIGN(32);
41 int dmalen = BUFSIZE;
42 
43 static void
sound_dmacallback(void)44 sound_dmacallback( void )
45 {
46   if( sfifo_used( &sound_fifo ) < 128) return;
47 
48   dmalen = MIN( BUFSIZE, sfifo_used( &sound_fifo ) );
49   sfifo_read( &sound_fifo, dmabuf, dmalen );
50   DCFlushRange( dmabuf, dmalen );
51   AUDIO_InitDMA( (u32)dmabuf, dmalen );
52   AUDIO_StartDMA();
53 }
54 
55 int
sound_lowlevel_init(const char * device,int * freqptr,int * stereoptr)56 sound_lowlevel_init( const char *device, int *freqptr, int *stereoptr )
57 {
58   switch(*freqptr) {
59   case 32000:
60     samplerate = AI_SAMPLERATE_32KHZ;
61     break;
62   case 48000:
63     samplerate = AI_SAMPLERATE_48KHZ;
64     break;
65   default:
66     printf("Sample rate %d not supported on Wii\n", *freqptr);
67     return 1;
68   }
69 
70   sfifo_init( &sound_fifo, BUFSIZE );
71   *stereoptr = 1;
72 
73   AUDIO_Init( NULL );
74   AUDIO_SetDSPSampleRate( samplerate );
75 
76 #ifndef DISPLAY_AUDIO
77   AUDIO_RegisterDMACallback( sound_dmacallback );
78   memset( dmabuf, 0, BUFSIZE );
79   AUDIO_InitDMA( (u32)dmabuf, BUFSIZE );
80   DCFlushRange( dmabuf, dmalen );
81   AUDIO_StartDMA();
82 #endif
83 
84   return 0;
85 }
86 
87 void
sound_lowlevel_end(void)88 sound_lowlevel_end( void )
89 {
90   sfifo_flush( &sound_fifo );
91   sfifo_close( &sound_fifo );
92   AUDIO_StopDMA();
93 }
94 
95 void
sound_lowlevel_frame(libspectrum_signed_word * data,int len)96 sound_lowlevel_frame(libspectrum_signed_word *data, int len)
97 {
98   int i;
99 
100   libspectrum_signed_byte *bytes = (libspectrum_signed_byte*)data;
101   len <<= 1;
102 
103   while(len) {
104     if( ( i = sfifo_write( &sound_fifo, bytes, len ) ) < 0 )
105       break;
106     else if( !i )
107       usleep(10000);
108     bytes += i;
109     len -= i;
110   }
111 }
112