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