1 /* $Id: Sound.cpp,v 1.29 2003/08/03 10:11:56 nan Exp $ */
2 
3 // Copyright (C) 2000-2003  ���� �ȹ�(Kanna Yoshihiro)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 #include "ttinc.h"
20 #include "Sound.h"
21 #include "Control.h"
22 
23 #ifdef WIN32
24 #include <io.h>
25 #endif
26 
27 extern long mode;
28 extern SDL_mutex *loadMutex;
29 
30 Sound* Sound::m_theSound = NULL;
31 
Sound()32 Sound::Sound() {
33 #ifdef HAVE_LIBSDL_MIXER
34   m_queuehead = m_queuetail = 0;
35 #else
36   m_soundMode = SOUND_NONE;
37 #endif
38 }
39 
~Sound()40 Sound::~Sound() {
41 #ifdef HAVE_LIBSDL_MIXER
42   for ( int i = 0 ; i < 16 ; i++ ) {
43     if ( m_sound[i] != 0 ) {
44       Mix_FreeChunk( m_sound[i] );
45       m_sound[i] = 0;
46     }
47   }
48 
49   if ( m_opening != 0 ) {
50     Mix_FreeMusic( m_opening );
51     m_opening = 0;
52   }
53 
54   Mix_CloseAudio();
55 #endif
56 }
57 
58 Sound*
TheSound()59 Sound::TheSound() {
60   if ( Sound::m_theSound )
61     return Sound::m_theSound;
62   else
63     return (Sound::m_theSound = new Sound());
64 }
65 
66 bool
Init(long sndMode)67 Sound::Init( long sndMode ) {
68   m_soundMode = sndMode;
69 
70 #ifdef HAVE_LIBSDL_MIXER
71   for ( int i = 0 ; i < 16 ; i++ ) {
72     m_sound[i] = 0;
73   }
74   m_opening = 0;
75 #endif
76 
77   if ( m_soundMode == SOUND_NONE )
78     return true;
79 
80 #ifdef HAVE_LIBSDL_MIXER
81 #ifdef WIN32
82   if ( Mix_OpenAudio( 44100, AUDIO_S16SYS, 2, 4096 ) < 0 ) {
83 #else
84   if ( Mix_OpenAudio( 44100, AUDIO_S16SYS, 2, 128 ) < 0 ) {
85 #endif
86     perror( _("SDL Mix_OpenAudio failed\n") );
87   }
88 
89   m_sound[SOUND_RACKET] = Mix_LoadWAV( "wav/racket.wav" );
90   m_sound[SOUND_TABLE] = Mix_LoadWAV( "wav/table.wav" );
91   m_sound[SOUND_CLICK] = Mix_LoadWAV( "wav/click.wav" );
92   m_sound[SOUND_LOVEALL] = Mix_LoadWAV( "wav/loveall.wav" );
93   m_sound[SOUND_ALL] = Mix_LoadWAV( "wav/all.wav" );
94 
95   m_score[0] = Mix_LoadWAV( "wav/zero.wav" );
96   m_score[1] = Mix_LoadWAV( "wav/one.wav" );
97   m_score[2] = Mix_LoadWAV( "wav/two.wav" );
98   m_score[3] = Mix_LoadWAV( "wav/three.wav" );
99   m_score[4] = Mix_LoadWAV( "wav/four.wav" );
100   m_score[5] = Mix_LoadWAV( "wav/five.wav" );
101   m_score[6] = Mix_LoadWAV( "wav/six.wav" );
102   m_score[7] = Mix_LoadWAV( "wav/seven.wav" );
103   m_score[8] = Mix_LoadWAV( "wav/eight.wav" );
104   m_score[9] = Mix_LoadWAV( "wav/nine.wav" );
105   m_score[10] = Mix_LoadWAV( "wav/ten.wav" );
106   m_score[11] = Mix_LoadWAV( "wav/eleven.wav" );
107   m_score[12] = Mix_LoadWAV( "wav/twelve.wav" );
108   m_score[13] = Mix_LoadWAV( "wav/thirteen.wav" );
109   m_score[14] = Mix_LoadWAV( "wav/fourteen.wav" );
110   m_score[15] = Mix_LoadWAV( "wav/fifteen.wav" );
111   m_score[16] = Mix_LoadWAV( "wav/sixteen.wav" );
112   m_score[17] = Mix_LoadWAV( "wav/seventeen.wav" );
113   m_score[18] = Mix_LoadWAV( "wav/eighteen.wav" );
114   m_score[19] = Mix_LoadWAV( "wav/nineteen.wav" );
115   m_score[20] = Mix_LoadWAV( "wav/twenty.wav" );
116   m_score[30] = Mix_LoadWAV( "wav/thirty.wav" );
117 
118   Mix_ChannelFinished( Sound::PlayFinishHandler );
119 #endif
120 
121   return true;
122 }
123 
124 void
125 Sound::Clear() {
126 #ifdef HAVE_LIBSDL_MIXER
127   for ( int i = 0 ; i < 16 ; i++ ) {
128     if ( m_sound[i] != 0 ) {
129       Mix_FreeChunk( m_sound[i] );
130       m_sound[i] = 0;
131     }
132   }
133 
134   if ( m_opening != 0 ) {
135     Mix_FreeMusic( m_opening );
136     m_opening = 0;
137   }
138 
139   Mix_ChannelFinished( NULL );
140   Mix_CloseAudio();
141 #endif
142 }
143 
144 bool
145 Sound::Play( long soundID, double x, double y ) {
146   if ( m_soundMode == SOUND_NONE )
147     return true;
148 
149 #ifdef HAVE_LIBSDL_MIXER
150   double srcX, srcY, srcZ;
151   double destX, destY, destZ;
152   double angle, destAngle;
153 
154   Control::TheControl()->LookAt( srcX, srcY, srcZ, destX, destY, destZ );
155 
156   destX -= srcX; destY -= srcY;
157   x -= srcX; y -= srcY;
158 
159   destAngle = acos( destX/hypot(destX, destY) );
160   if ( destY < 0 )
161     destAngle += 3.14159265;
162 
163   angle = acos( x/hypot(x, y) );
164   if ( y < 0 )
165     angle += 3.14159265;
166 
167   angle -= destAngle;
168 
169   Mix_SetPosition( 0, (int)(angle*180.0/3.14159265), hypot(x, y)*8 );
170   Mix_PlayChannel( 0, m_sound[soundID], 0 );
171 #endif
172 
173   return true;
174 }
175 
176 bool
177 Sound::PlayScore( long score1, long score2 ) {
178   if ( m_soundMode == SOUND_NONE )
179     return true;
180 
181 #ifdef HAVE_LIBSDL_MIXER
182   double x = -TABLEWIDTH/2-0.5;
183   double y = 0;
184   double srcX, srcY, srcZ;
185   double destX, destY, destZ;
186   double angle, destAngle;
187 
188   Control::TheControl()->LookAt( srcX, srcY, srcZ, destX, destY, destZ );
189 
190   destX -= srcX; destY -= srcY;
191   x -= srcX; y -= srcY;
192 
193   destAngle = acos( destX/hypot(destX, destY) );
194   if ( destY < 0 )
195     destAngle += 3.14159265;
196 
197   angle = acos( x/hypot(x, y) );
198   if ( y < 0 )
199     angle += 3.14159265;
200 
201   angle -= destAngle;
202 
203   Mix_SetPosition( 0, (int)(angle*180.0/3.14159265), hypot(x, y)*8 );
204   PlayNumber( score1 );
205   if ( score1 == score2 )
206     PlayBlocking( 1, m_sound[SOUND_ALL] );
207   else
208     PlayNumber( score2 );
209 #endif
210 
211   return true;
212 }
213 
214 bool
215 Sound::PlayNumber( long number ) {
216   if ( m_soundMode == SOUND_NONE )
217     return true;
218 
219 #ifdef HAVE_LIBSDL_MIXER
220   number %= 40;
221   if ( number > 30 ) {
222     PlayBlocking( 1, m_score[30] );
223     PlayBlocking( 1, m_score[number-30] );
224   } else if ( number > 20 ) {
225     PlayBlocking( 1, m_score[20] );
226     PlayBlocking( 1, m_score[number-20] );
227   } else
228     PlayBlocking( 1, m_score[number] );
229 #endif
230 
231   return true;
232 }
233 
234 /* Play the sound on blocking mode */
235 bool
236 Sound::PlayBlocking( int channel, Mix_Chunk *chunk ) {
237   if ( !Mix_Playing( channel ) ) {
238     Mix_PlayChannel( channel, chunk, 0 );
239   } else {
240     m_chunkqueue[m_queuetail%SOUND_QUEUESIZE] = chunk;
241     m_queuetail++;
242   }
243 
244   return true;
245 }
246 
247 void
248 Sound::PlayFinishHandler( int channel ) {
249   if ( channel != 1 )
250     return;
251 
252   if ( Sound::TheSound()->m_queuehead != Sound::TheSound()->m_queuetail ) {
253     Mix_PlayChannel( channel,
254 		     Sound::TheSound()->
255 		     m_chunkqueue[Sound::TheSound()->
256 				 m_queuehead%SOUND_QUEUESIZE],
257 		     0 );
258     Sound::TheSound()->m_queuehead++;
259   }
260 }
261 
262 long
263 Sound::GetSoundMode() {
264   return m_soundMode;
265 }
266 
267 long
268 Sound::InitBGM( char *filename ) {
269   if ( m_soundMode == SOUND_NONE )
270     return true;
271 
272 #ifdef HAVE_LIBSDL_MIXER
273   m_opening = Mix_LoadMUS( OPENINGFILENAME );
274 
275   if ( m_opening == 0 )
276     printf( "%s\n", SDL_GetError() );
277 #endif
278 
279   return 0;
280 }
281 
282 // It is better to move it to other thread
283 long
284 Sound::PlayBGM() {
285   if ( m_soundMode == SOUND_NONE )
286     return true;
287 
288 #ifdef HAVE_LIBSDL_MIXER
289   Mix_PlayMusic( m_opening, 1 );
290 #endif
291 
292   return 0;
293 }
294 
295 long
296 Sound::StopBGM() {
297   if ( m_soundMode == SOUND_NONE )
298     return true;
299 
300 #ifdef HAVE_LIBSDL_MIXER
301   Mix_FadeOutMusic( 2000 );
302 #endif
303 
304   return 0;
305 }
306