00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLAudio.h"
00028
00029
00030 #include "OSDLUtils.h"
00031 #include "OSDLBasic.h"
00032
00033 #include "OSDLAudioChannel.h"
00034 #include "OSDLMusic.h"
00035 #include "OSDLMusicManager.h"
00036
00037
00038
00039 #ifdef OSDL_USES_CONFIG_H
00040 #include "OSDLConfig.h"
00041 #endif // OSDL_USES_CONFIG_H
00042
00043
00044 #if OSDL_ARCH_NINTENDO_DS
00045 #include "OSDLConfigForNintendoDS.h"
00046 #endif // OSDL_ARCH_NINTENDO_DS
00047
00048
00049
00050 #if OSDL_USES_SDL
00051 #include "SDL.h"
00052 #endif // OSDL_USES_SDL
00053
00054 #if OSDL_USES_SDL_MIXER
00055 #include "SDL_mixer.h"
00056 #endif // OSDL_USES_SDL_MIXER
00057
00058
00059 #include <list>
00060 using std::list ;
00061
00062 using std::string ;
00063 using std::vector ;
00064
00065 using Ceylan::Maths::Hertz ;
00066
00067
00068 using namespace Ceylan::Log ;
00069
00070 using namespace OSDL::Audio ;
00071
00072
00073
00074
00075 #if OSDL_VERBOSE_AUDIO_MODULE
00076
00077 #define LOG_DEBUG_AUDIO(message) LogPlug::debug(message)
00078 #define LOG_TRACE_AUDIO(message) LogPlug::trace(message)
00079 #define LOG_WARNING_AUDIO(message) LogPlug::warning(message)
00080
00081 #else // OSDL_DEBUG_AUDIO_PLAYBACK
00082
00083 #define LOG_DEBUG_AUDIO(message)
00084 #define LOG_TRACE_AUDIO(message)
00085 #define LOG_WARNING_AUDIO(message)
00086
00087 #endif // OSDL_DEBUG_AUDIO_PLAYBACK
00088
00089
00090
00091 string OSDL::Audio::AudioModule::AudioPathEnvironmentVariable = "AUDIO_PATH" ;
00092
00093
00094
00095 Ceylan::System::FileLocator OSDL::Audio::AudioModule::AudioFileLocator(
00096 AudioPathEnvironmentVariable ) ;
00097
00098
00099
00100
00101 #if OSDL_USES_SDL
00102
00103 const SampleFormat AudioModule::Uint8SampleFormat = AUDIO_U8 ;
00104 const SampleFormat AudioModule::Sint8SampleFormat = AUDIO_S8 ;
00105
00106
00107 const SampleFormat AudioModule::LittleUint16SampleFormat = AUDIO_U16LSB ;
00108 const SampleFormat AudioModule::LittleSint16SampleFormat = AUDIO_S16LSB ;
00109
00110 const SampleFormat AudioModule::BigUint16SampleFormat = AUDIO_U16MSB ;
00111 const SampleFormat AudioModule::BigSint16SampleFormat = AUDIO_S16MSB ;
00112
00113 const SampleFormat AudioModule::NativeUint16SampleFormat = AUDIO_U16SYS ;
00114 const SampleFormat AudioModule::NativeSint16SampleFormat = AUDIO_S16SYS ;
00115
00116 #else // OSDL_USES_SDL
00117
00118
00119
00120
00121 const SampleFormat AudioModule::Uint8SampleFormat = 0x0008 ;
00122 const SampleFormat AudioModule::Sint8SampleFormat = 0x8008 ;
00123
00124
00125 const SampleFormat AudioModule::LittleUint16SampleFormat = 0x0010 ;
00126 const SampleFormat AudioModule::LittleSint16SampleFormat = 0x8010 ;
00127
00128 const SampleFormat AudioModule::BigUint16SampleFormat = 0x1010 ;
00129 const SampleFormat AudioModule::BigSint16SampleFormat = 0x9010 ;
00130
00131
00132 #if CEYLAN_DETECTED_LITTLE_ENDIAN
00133
00134 const SampleFormat AudioModule::NativeUint16SampleFormat = 0x0010 ;
00135 const SampleFormat AudioModule::NativeSint16SampleFormat = 0x8010 ;
00136
00137 #else // CEYLAN_DETECTED_LITTLE_ENDIAN
00138
00139 const SampleFormat AudioModule::NativeUint16SampleFormat = 0x1010 ;
00140 const SampleFormat AudioModule::NativeSint16SampleFormat = 0x9010 ;
00141
00142 #endif // CEYLAN_DETECTED_LITTLE_ENDIAN
00143
00144
00145 #endif // OSDL_USES_SDL
00146
00147
00148
00149 const SampleFormat AudioModule::IMAADPCMSampleFormat = 0x0012 ;
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 const ChannelFormat AudioModule::Mono = 1 ;
00163 const ChannelFormat AudioModule::Stereo = 2 ;
00164
00165
00166 const Volume AudioModule::MinVolume = 0 ;
00167 const Volume AudioModule::MaxVolume = 128 ;
00168
00169
00170
00171
00172
00173 std::string OSDL::Audio::sampleFormatToString( SampleFormat format )
00174 {
00175
00176 switch( format )
00177 {
00178
00179 case AudioModule::Uint8SampleFormat:
00180 return "unsigned 8-bit" ;
00181 break ;
00182
00183 case AudioModule::Sint8SampleFormat:
00184 return "signed 8-bit" ;
00185 break ;
00186
00187 case AudioModule::LittleUint16SampleFormat:
00188 #if CEYLAN_DETECTED_LITTLE_ENDIAN
00189 return "little-endian unsigned 16-bit (native)" ;
00190 #else // CEYLAN_DETECTED_LITTLE_ENDIAN
00191 return "little-endian unsigned 16-bit (non native)" ;
00192 #endif // CEYLAN_DETECTED_LITTLE_ENDIAN
00193 break ;
00194
00195 case AudioModule::LittleSint16SampleFormat:
00196 #if CEYLAN_DETECTED_LITTLE_ENDIAN
00197 return "little-endian signed 16-bit (native)" ;
00198 #else // CEYLAN_DETECTED_LITTLE_ENDIAN
00199 return "little-endian signed 16-bit (non native)" ;
00200 #endif // CEYLAN_DETECTED_LITTLE_ENDIAN
00201 break ;
00202
00203 case AudioModule::BigUint16SampleFormat:
00204 #if CEYLAN_DETECTED_LITTLE_ENDIAN
00205 return "big-endian unsigned 16-bit (non native)" ;
00206 #else // CEYLAN_DETECTED_LITTLE_ENDIAN
00207 return "big-endian unsigned 16-bit (native)" ;
00208 #endif // CEYLAN_DETECTED_LITTLE_ENDIAN
00209 break ;
00210
00211 case AudioModule::BigSint16SampleFormat:
00212 #if CEYLAN_DETECTED_LITTLE_ENDIAN
00213 return "big-endian signed 16-bit (non native)" ;
00214 #else // CEYLAN_DETECTED_LITTLE_ENDIAN
00215 return "big-endian signed 16-bit (native)" ;
00216 #endif // CEYLAN_DETECTED_LITTLE_ENDIAN
00217 break ;
00218
00219 case AudioModule::IMAADPCMSampleFormat:
00220 return "IMA ADPCM (non Microsoft)" ;
00221 break ;
00222
00223 default:
00224 throw AudioException( "OSDL::Audio::sampleFormatToString failed: "
00225 "unknown sample format (" + Ceylan::toString( format ) + ")" ) ;
00226 break ;
00227
00228 }
00229
00230 }
00231
00232
00233
00234 std::string OSDL::Audio::channelFormatToString( SampleFormat format )
00235 {
00236
00237 switch( format )
00238 {
00239
00240 case AudioModule::Mono:
00241 return "mono" ;
00242 break ;
00243
00244 case AudioModule::Stereo:
00245 return "stereo" ;
00246 break ;
00247
00248 default:
00249 throw AudioException( "OSDL::Audio::channelFormatToString failed: "
00250 "unknown channel format ("
00251 + Ceylan::toString( format ) + ")" ) ;
00252 break ;
00253
00254 }
00255
00256 }
00257
00258
00259
00260
00261
00262 bool AudioModule::_AudioInitialized = false ;
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 #if OSDL_USES_SDL
00293
00295 const string AudioModule::SDLEnvironmentVariables[] =
00296 {
00297
00298 "AUDIODEV",
00299 "SDL_AUDIODRIVER",
00300 "SDL_DISKAUDIOFILE",
00301 "SDL_DISKAUDIODELAY",
00302 "SDL_DSP_NOSELECT",
00303 "SDL_PATH_DSP"
00304
00305 } ;
00306
00307 #else // OSDL_USES_SDL
00308
00309 const string AudioModule::SDLEnvironmentVariables[] = {} ;
00310
00311 #endif // OSDL_USES_SDL
00312
00313
00314
00315
00316 const Ceylan::Uint16 AudioModule::DriverNameMaximumLength = 50 ;
00317
00318
00319
00320
00321
00322 AudioModule::AudioModule() :
00323 Ceylan::Module(
00324 "OSDL audio module",
00325 "This is the audio module of OSDL",
00326 "http://osdl.sourceforge.net",
00327 "Olivier Boudeville",
00328 "olivier.boudeville@online.fr",
00329 OSDL::GetVersion(),
00330 "disjunctive LGPL/GPL" ),
00331 _mixerInitialized( false ),
00332 _chunkSize( 0 ),
00333 _controlMusicManager( true ),
00334 _isGuiEnabled( false )
00335 {
00336
00337 send( "Initializing audio subsystem." ) ;
00338
00339 #if OSDL_USES_SDL
00340
00341 if ( SDL_InitSubSystem(
00342 CommonModule::UseAudio ) != CommonModule::BackendSuccess )
00343 throw AudioException( "AudioModule constructor: "
00344 "unable to initialize audio subsystem: "
00345 + Utils::getBackendLastError() ) ;
00346
00347 #if OSDL_USES_SDL_MIXER
00348
00349 SDL_version compileTimeSDLMixerVersion ;
00350 MIX_VERSION( & compileTimeSDLMixerVersion ) ;
00351
00352 SDL_version linkTimeSDLMixerVersion = *Mix_Linked_Version() ;
00353
00354 send( "Using SDL_mixer backend, compiled against the "
00355 + Ceylan::toNumericalString( compileTimeSDLMixerVersion.major) + "."
00356 + Ceylan::toNumericalString( compileTimeSDLMixerVersion.minor) + "."
00357 + Ceylan::toNumericalString( compileTimeSDLMixerVersion.patch)
00358 + " version, linked against the "
00359 + Ceylan::toNumericalString( linkTimeSDLMixerVersion.major) + "."
00360 + Ceylan::toNumericalString( linkTimeSDLMixerVersion.minor) + "."
00361 + Ceylan::toNumericalString( linkTimeSDLMixerVersion.patch)
00362 + " version." ) ;
00363
00364
00365
00366 ::Mix_Init( MIX_INIT_OGG ) ;
00367
00368
00369
00370 ::Mix_HookMusicFinished( HandleMusicPlaybackFinishedCallback ) ;
00371
00372
00373
00374 if ( _controlMusicManager )
00375 {
00376
00377 if ( MusicManager::_CurrentMusicManager != 0 )
00378 throw AudioException( "AudioModule constructor failed: "
00379 "there is already a music manager registered." ) ;
00380
00381 MusicManager::_CurrentMusicManager = new MusicManager() ;
00382
00383 }
00384
00385 #endif // OSDL_USES_SDL_MIXER
00386
00387
00388 #else // OSDL_USES_SDL
00389
00390 #if OSDL_ARCH_NINTENDO_DS
00391
00392
00393 #ifdef OSDL_RUNS_ON_ARM7
00394
00395
00396
00397 #elif defined(OSDL_RUNS_ON_ARM9)
00398
00399 CommandManager::GetCommandManager().enableMusicSupport() ;
00400
00401 #endif // OSDL_RUNS_ON_ARM7
00402
00403
00404
00405 #endif // OSDL_ARCH_NINTENDO_DS
00406
00407 #endif // OSDL_USES_SDL
00408
00409 _AudioInitialized = true ;
00410
00411
00412 send( "Audio subsystem initialized." ) ;
00413
00414 dropIdentifier() ;
00415
00416 }
00417
00418
00419
00420 AudioModule::~AudioModule() throw()
00421 {
00422
00423 send( "Stopping audio subsystem." ) ;
00424
00425 if ( _controlMusicManager )
00426 {
00427
00428 if ( MusicManager::_CurrentMusicManager != 0 )
00429 {
00430
00431 delete MusicManager::_CurrentMusicManager ;
00432 MusicManager::_CurrentMusicManager = 0 ;
00433
00434 }
00435 else
00436 {
00437
00438 LogPlug::error( "AudioModule destructor: "
00439 "no music manager found." ) ;
00440
00441 }
00442
00443 }
00444
00445
00446 if ( _mixerInitialized )
00447 {
00448
00449 try
00450 {
00451
00452 unsetMode() ;
00453
00454 }
00455 catch( const AudioException & e )
00456 {
00457
00458 LogPlug::error( "AudioModule destructor: "
00459 "unsetting of the mixer failed: " + e.toString() ) ;
00460 }
00461
00462 }
00463
00464
00465 #if OSDL_USES_SDL
00466
00467 SDL_QuitSubSystem( CommonModule::UseAudio ) ;
00468
00469 #else // OSDL_USES_SDL
00470
00471 #if OSDL_ARCH_NINTENDO_DS
00472
00473
00474 #ifdef OSDL_RUNS_ON_ARM7
00475
00476 #elif defined(OSDL_RUNS_ON_ARM9)
00477
00478 #endif // OSDL_RUNS_ON_ARM7
00479
00480 #endif // OSDL_ARCH_NINTENDO_DS
00481
00482 #endif // OSDL_USES_SDL
00483
00484 _AudioInitialized = false ;
00485
00486 send( "Audio subsystem stopped." ) ;
00487
00488 }
00489
00490
00491
00492 void AudioModule::setMode( Hertz outputFrequency,
00493 SampleFormat outputSampleFormat, ChannelFormat outputChannel,
00494 ChunkSize outputBufferSize, ChannelNumber mixingChannelCount )
00495 {
00496
00497 #if OSDL_USES_SDL_MIXER
00498
00499 if ( _mixerInitialized )
00500 throw AudioException( "AudioModule::setMode failed: "
00501 "mixing mode already set, and not unset yet." ) ;
00502
00503
00504
00505
00506
00507
00508 if ( ::Mix_OpenAudio( outputFrequency, outputSampleFormat,
00509 GetChannelCountFor( outputChannel ), outputBufferSize ) != 0 )
00510 throw AudioException( "AudioModule::setMode failed: "
00511 + string( ::Mix_GetError() )
00512 + ". Maybe the audio driver is used by another application?" ) ;
00513
00514 _chunkSize = outputBufferSize ;
00515
00516 ChannelNumber channelCount = ::Mix_AllocateChannels( mixingChannelCount ) ;
00517
00518 if ( channelCount != mixingChannelCount )
00519 throw AudioException( "AudioModule::setMode: wanted "
00520 + Ceylan::toString( mixingChannelCount )
00521 + " input mixing channel(s), but got "
00522 + Ceylan::toString( _inputChannels.size() )
00523 + " channel(s) instead" ) ;
00524
00525 try
00526 {
00527
00528 for ( ChannelNumber i = 0; i < channelCount; i++ )
00529 _inputChannels.push_back( new AudioChannel( i ) ) ;
00530
00531 }
00532 catch( const AudioChannelException & e )
00533 {
00534
00535 throw AudioException(
00536 "AudioModule::setMode failed when creating mixing channels: "
00537 + e.toString() ) ;
00538
00539 }
00540
00541 _mixerInitialized = true ;
00542
00543 #else // OSDL_USES_SDL_MIXER
00544
00545 throw AudioException( "AudioModule::setMode failed: "
00546 "no SDL_mixer support available" ) ;
00547
00548 #endif // OSDL_USES_SDL_MIXER
00549
00550 }
00551
00552
00553
00554 Ceylan::System::Millisecond AudioModule::getObtainedMode(
00555 Hertz & actualOutputFrequency, SampleFormat & actualOutputSampleFormat,
00556 ChannelNumber & actualOutputChannelCount )
00557 {
00558
00559 #if OSDL_USES_SDL_MIXER
00560
00561
00562 int channelNumber, frequency ;
00563
00564 if ( ::Mix_QuerySpec( & frequency, & actualOutputSampleFormat,
00565 & channelNumber ) == 0 )
00566 throw AudioException( " AudioModule::getObtainedMode failed: "
00567 + string( ::Mix_GetError() ) ) ;
00568
00569 actualOutputChannelCount = channelNumber ;
00570 actualOutputFrequency = frequency ;
00571
00572
00573 return static_cast<Ceylan::System::Millisecond>(
00574 1000.0f / 2 * _chunkSize /
00575 ( actualOutputFrequency * actualOutputChannelCount
00576 * GetSampleSizeFor( actualOutputSampleFormat ) ) ) ;
00577
00578 #else // OSDL_USES_SDL_MIXER
00579
00580 throw AudioException( "AudioModule::getObtainedMode failed: "
00581 "no SDL_mixer support available" ) ;
00582
00583 #endif // OSDL_USES_SDL_MIXER
00584
00585 }
00586
00587
00588
00589 void AudioModule::unsetMode()
00590 {
00591
00592
00593
00594 #if OSDL_USES_SDL_MIXER
00595
00596 if ( _mixerInitialized )
00597 {
00598
00599 ::Mix_CloseAudio() ;
00600 _mixerInitialized = false ;
00601 _chunkSize = 0 ;
00602
00603 for ( vector<AudioChannel *>::iterator it = _inputChannels.begin();
00604 it != _inputChannels.end(); it++ )
00605 delete (*it) ;
00606
00607 _inputChannels.clear() ;
00608
00609 }
00610 else
00611 {
00612
00613 LOG_WARNING_AUDIO( "AudioModule::unsetMode called "
00614 "whereas not already initialized, nothing done." ) ;
00615
00616 }
00617
00618 ::Mix_Quit() ;
00619
00620 #else // OSDL_USES_SDL_MIXER
00621
00622 throw AudioException( "AudioModule::unsetMode failed: "
00623 "no SDL_mixer support available" ) ;
00624
00625 #endif // OSDL_USES_SDL_MIXER
00626
00627 }
00628
00629
00630
00631 void AudioModule::setPanning( Ceylan::Maths::Percentage leftPercentage )
00632 {
00633
00634 #if OSDL_USES_SDL_MIXER
00635
00636 Ceylan::Uint8 left = static_cast<Ceylan::Uint8>(
00637 ( leftPercentage * 254 ) / 100 ) ;
00638
00639 if ( ::Mix_SetPanning( MIX_CHANNEL_POST, left,
00640 254 - left ) == 0 )
00641 throw AudioException( "AudioModule::setPanning failed: "
00642 + string( ::Mix_GetError() ) ) ;
00643
00644 #else // OSDL_USES_SDL_MIXER
00645
00646 throw AudioException( "AudioModule::setPanning failed: "
00647 "no SDL_mixer support available" ) ;
00648
00649 #endif // OSDL_USES_SDL_MIXER
00650
00651 }
00652
00653
00654
00655 void AudioModule::unsetPanning()
00656 {
00657
00658 #if OSDL_USES_SDL_MIXER
00659
00660 if ( ::Mix_SetPanning( MIX_CHANNEL_POST, 255,
00661 255 ) == 0 )
00662 throw AudioException( "AudioModule::unsetPanning failed: "
00663 + string( ::Mix_GetError() ) ) ;
00664
00665 #else // OSDL_USES_SDL_MIXER
00666
00667 throw AudioException( "AudioModule::unsetPanning failed: "
00668 "no SDL_mixer support available" ) ;
00669
00670 #endif // OSDL_USES_SDL_MIXER
00671
00672 }
00673
00674
00675
00676 void AudioModule::setReverseStereo( bool reverse )
00677 {
00678
00679 #if OSDL_USES_SDL_MIXER
00680
00681 if ( ::Mix_SetReverseStereo( MIX_CHANNEL_POST,
00682 ( ( reverse == true ) ? 1 : 0 ) ) == 0 )
00683 throw AudioException( "AudioModule::setReverseStereo failed: "
00684 + string( ::Mix_GetError() ) ) ;
00685
00686 #else // OSDL_USES_SDL_MIXER
00687
00688 throw AudioException( "AudioModule::setReverseStereo failed: "
00689 "no SDL_mixer support available" ) ;
00690
00691 #endif // OSDL_USES_SDL_MIXER
00692
00693 }
00694
00695
00696
00697 void AudioModule::setDistanceAttenuation( ListenerDistance distance )
00698 {
00699
00700 #if OSDL_USES_SDL_MIXER
00701
00702 if ( ::Mix_SetDistance( MIX_CHANNEL_POST, distance )
00703 == 0 )
00704 throw AudioException( "AudioModule::setDistanceAttenuation failed: "
00705 + string( ::Mix_GetError() ) ) ;
00706
00707 #else // OSDL_USES_SDL_MIXER
00708
00709 throw AudioException( "AudioModule::setDistanceAttenuation failed: "
00710 "no SDL_mixer support available" ) ;
00711
00712 #endif // OSDL_USES_SDL_MIXER
00713
00714 }
00715
00716
00717
00718 void AudioModule::unsetDistanceAttenuation()
00719 {
00720
00721 #if OSDL_USES_SDL_MIXER
00722
00723 if ( ::Mix_SetDistance( MIX_CHANNEL_POST, 0 ) == 0 )
00724 throw AudioException( "AudioModule::unsetDistanceAttenuation failed: "
00725 + string( ::Mix_GetError() ) ) ;
00726
00727 #else // OSDL_USES_SDL_MIXER
00728
00729 throw AudioException( "AudioModule::unsetDistanceAttenuation failed: "
00730 "no SDL_mixer support available" ) ;
00731
00732 #endif // OSDL_USES_SDL_MIXER
00733
00734 }
00735
00736
00737
00738 void AudioModule::setPositionAttenuation( ListenerDistance distance,
00739 ListenerAngle angle )
00740 {
00741
00742 #if OSDL_USES_SDL_MIXER
00743
00744 if ( ::Mix_SetPosition( MIX_CHANNEL_POST,
00745 angle, distance ) == 0 )
00746 throw AudioException( "AudioModule::setPositionAttenuation failed: "
00747 + string( ::Mix_GetError() ) ) ;
00748
00749 #else // OSDL_USES_SDL_MIXER
00750
00751 throw AudioException( "AudioModule::setPositionAttenuation failed: "
00752 "no SDL_mixer support available" ) ;
00753
00754 #endif // OSDL_USES_SDL_MIXER
00755
00756 }
00757
00758
00759
00760 void AudioModule::unsetPositionAttenuation()
00761 {
00762
00763 #if OSDL_USES_SDL_MIXER
00764
00765 if ( ::Mix_SetPosition( MIX_CHANNEL_POST, 0, 0 ) == 0 )
00766 throw AudioException( "AudioModule::unsetPositionAttenuation failed: "
00767 + string( ::Mix_GetError() ) ) ;
00768
00769 #else // OSDL_USES_SDL_MIXER
00770
00771 throw AudioException( "AudioModule::unsetPositionAttenuation failed: "
00772 "no SDL_mixer support available" ) ;
00773
00774 #endif // OSDL_USES_SDL_MIXER
00775
00776 }
00777
00778
00779
00780 bool AudioModule::isGUIEnabled() const
00781 {
00782
00783 return _isGuiEnabled ;
00784
00785 }
00786
00787
00788
00789 void AudioModule::setGUIEnableStatus( bool newStatus )
00790 {
00791
00792 _isGuiEnabled = newStatus ;
00793
00794 }
00795
00796
00797
00798 MusicType AudioModule::getTypeOfCurrentMusic() const
00799 {
00800
00801 #if OSDL_USES_SDL_MIXER
00802
00803 return Music::GetTypeOf( 0 ) ;
00804
00805 #else // OSDL_USES_SDL_MIXER
00806
00807 throw AudioException( "AudioModule::getTypeOfCurrentMusic failed: "
00808 "no SDL_mixer support available" ) ;
00809
00810 #endif // OSDL_USES_SDL_MIXER
00811
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 ChannelNumber AudioModule::getMixingChannelCount() const
00825 {
00826
00827 #if OSDL_USES_SDL_MIXER
00828
00829 #if OSDL_DEBUG
00830
00831 if ( ::Mix_AllocateChannels( -1 ) !=
00832 static_cast<int>( _inputChannels.size() ) )
00833 throw AudioException( "AudioModule::getMixingChannelCount failed: "
00834 "inconsistency in channel count" ) ;
00835
00836 #endif // OSDL_DEBUG
00837
00838
00839 return ::Mix_AllocateChannels( -1 ) ;
00840
00841 #else // OSDL_USES_SDL_MIXER
00842
00843 throw AudioException( "AudioModule::getMixingChannelCount failed: "
00844 "no SDL_mixer support available" ) ;
00845
00846 #endif // OSDL_USES_SDL_MIXER
00847
00848 }
00849
00850
00851
00852 AudioChannel & AudioModule::getMixingChannelAt( ChannelNumber index ) const
00853 {
00854
00855 try
00856 {
00857
00858 return *_inputChannels.at( index ) ;
00859
00860 }
00861 catch( const std::exception & e )
00862 {
00863
00864 throw AudioException( "AudioModule::getMixingChannelAt out of bounds: "
00865 + string( e.what() ) ) ;
00866 }
00867
00868 }
00869
00870
00871
00872 void AudioModule::setVolumeForAllMixingChannels( Volume newVolume )
00873 {
00874
00875 #if OSDL_USES_SDL_MIXER
00876
00877 ::Mix_Volume( -1, newVolume ) ;
00878
00879 #else // OSDL_USES_SDL_MIXER
00880
00881 throw AudioException( "AudioModule::setVolumeForAllMixingChannels failed: "
00882 "no SDL_mixer support available" ) ;
00883
00884 #endif // OSDL_USES_SDL_MIXER
00885
00886 }
00887
00888
00889
00890 ChannelNumber AudioModule::getPlayingChannelCount() const
00891 {
00892
00893 #if OSDL_USES_SDL_MIXER
00894
00895 return ::Mix_Playing( -1 ) ;
00896
00897 #else // OSDL_USES_SDL_MIXER
00898
00899 throw AudioException( "AudioModule::getPlayingChannelCount failed: "
00900 "no SDL_mixer support available" ) ;
00901
00902 #endif // OSDL_USES_SDL_MIXER
00903
00904 }
00905
00906
00907
00908 ChannelNumber AudioModule::getPausedChannelCount() const
00909 {
00910
00911 #if OSDL_USES_SDL_MIXER
00912
00913 return ::Mix_Paused( -1 ) ;
00914
00915 #else // OSDL_USES_SDL_MIXER
00916
00917 throw AudioException( "AudioModule::getPausedChannelCount failed: "
00918 "no SDL_mixer support available" ) ;
00919
00920 #endif // OSDL_USES_SDL_MIXER
00921
00922 }
00923
00924
00925
00926 void AudioModule::pauseAllChannels()
00927 {
00928
00929 #if OSDL_USES_SDL_MIXER
00930
00931 ::Mix_Pause( -1 ) ;
00932
00933 #else // OSDL_USES_SDL_MIXER
00934
00935 throw AudioException( "AudioModule::pauseAllChannels failed: "
00936 "no SDL_mixer support available" ) ;
00937
00938 #endif // OSDL_USES_SDL_MIXER
00939
00940 }
00941
00942
00943
00944 void AudioModule::resumeAllChannels()
00945 {
00946
00947 #if OSDL_USES_SDL_MIXER
00948
00949 ::Mix_Resume( -1 ) ;
00950
00951 #else // OSDL_USES_SDL_MIXER
00952
00953 throw AudioException( "AudioModule::resumeAllChannels failed: "
00954 "no SDL_mixer support available" ) ;
00955
00956 #endif // OSDL_USES_SDL_MIXER
00957
00958 }
00959
00960
00961
00962 void AudioModule::haltAllChannels()
00963 {
00964
00965 #if OSDL_USES_SDL_MIXER
00966
00967 ::Mix_HaltChannel( -1 ) ;
00968
00969 #else // OSDL_USES_SDL_MIXER
00970
00971 throw AudioException( "AudioModule::haltAllChannels failed: "
00972 "no SDL_mixer support available" ) ;
00973
00974 #endif // OSDL_USES_SDL_MIXER
00975
00976 }
00977
00978
00979
00980 ChannelNumber AudioModule::expireAllChannelsIn(
00981 Ceylan::System::Millisecond expireDuration )
00982 {
00983
00984 #if OSDL_USES_SDL_MIXER
00985
00986 return ::Mix_ExpireChannel( -1, expireDuration ) ;
00987
00988 #else // OSDL_USES_SDL_MIXER
00989
00990 throw AudioException( "AudioModule::expireAllChannelsIn failed: "
00991 "no SDL_mixer support available" ) ;
00992
00993 #endif // OSDL_USES_SDL_MIXER
00994
00995 }
00996
00997
00998
00999 ChannelNumber AudioModule::fadeOutAllChannelsDuring(
01000 Ceylan::System::Millisecond fadeOutDuration )
01001 {
01002
01003 #if OSDL_USES_SDL_MIXER
01004
01005 return ::Mix_FadeOutChannel( -1, fadeOutDuration ) ;
01006
01007 #else // OSDL_USES_SDL_MIXER
01008
01009 throw AudioException( "AudioModule::fadeOutAllChannelsDuring failed: "
01010 "no SDL_mixer support available" ) ;
01011
01012 #endif // OSDL_USES_SDL_MIXER
01013
01014 }
01015
01016
01017
01018 bool AudioModule::isMusicPlaying() const
01019 {
01020
01021 #if OSDL_USES_SDL_MIXER
01022
01023 return ( ::Mix_PlayingMusic() == 1 ) ; ;
01024
01025 #else // OSDL_USES_SDL_MIXER
01026
01027 throw AudioException( "AudioModule::isMusicPlaying failed: "
01028 "no SDL_mixer support available" ) ;
01029
01030 #endif // OSDL_USES_SDL_MIXER
01031
01032 }
01033
01034
01035
01036 bool AudioModule::isMusicPaused() const
01037 {
01038
01039 #if OSDL_USES_SDL_MIXER
01040
01041 return ( ::Mix_PausedMusic() == 1 ) ; ;
01042
01043 #else // OSDL_USES_SDL_MIXER
01044
01045 throw AudioException( "AudioModule::isMusicPaused failed: "
01046 "no SDL_mixer support available" ) ;
01047
01048 #endif // OSDL_USES_SDL_MIXER
01049
01050 }
01051
01052
01053
01054 FadingStatus AudioModule::getMusicFadingStatus() const
01055 {
01056
01057 #if OSDL_USES_SDL_MIXER
01058
01059 switch( ::Mix_FadingMusic() )
01060 {
01061
01062 case MIX_NO_FADING:
01063 return None ;
01064 break ;
01065
01066 case MIX_FADING_OUT:
01067 return Out ;
01068 break ;
01069
01070 case MIX_FADING_IN:
01071 return In ;
01072 break ;
01073
01074 default:
01075 LogPlug::error(
01076 " AudioModule::getMusicFadingStatus: unexpected status" ) ;
01077 return None ;
01078 break ;
01079
01080 }
01081
01082 #else // OSDL_USES_SDL_MIXER
01083
01084 throw AudioException( "AudioModule::getMusicFadingStatus failed: "
01085 "no SDL_mixer support available" ) ;
01086
01087 #endif // OSDL_USES_SDL_MIXER
01088
01089 }
01090
01091
01092
01093 std::string AudioModule::getDriverName() const
01094 {
01095
01096 return AudioModule::GetDriverName() ;
01097
01098 }
01099
01100
01101
01102 const string AudioModule::toString( Ceylan::VerbosityLevels level ) const
01103 {
01104
01105
01106 string res = "Audio module, " ;
01107
01108 if ( ! _mixerInitialized )
01109 {
01110
01111 res += "mixer not initialized" ;
01112
01113 }
01114 else
01115 {
01116
01117 res += "mixer is initialized. Chunk size is "
01118 + Ceylan::toString( _chunkSize )
01119 + " bytes. There are " + Ceylan::toString( _inputChannels.size() )
01120 + " input mixing channel(s)" ;
01121
01122 }
01123
01124 if ( level == Ceylan::low )
01125 return res ;
01126
01127 res += ". " + Ceylan::Module::toString() ;
01128
01129 return res ;
01130
01131 }
01132
01133
01134
01135 string AudioModule::DescribeEnvironmentVariables()
01136 {
01137
01138 #if OSDL_USES_SDL
01139
01140 Ceylan::Uint16 varCount =
01141 sizeof( SDLEnvironmentVariables ) / sizeof (string) ;
01142
01143 string result = "Examining the " + Ceylan::toString( varCount )
01144 + " audio-related environment variables for SDL backend:" ;
01145
01146 list<string> variables ;
01147
01148 string var, value ;
01149
01150 TextOutputFormat htmlFormat = Ceylan::TextDisplayable::GetOutputFormat() ;
01151
01152 for ( Ceylan::Uint16 i = 0; i < varCount; i++ )
01153 {
01154 var = SDLEnvironmentVariables[ i ] ;
01155 value = Ceylan::System::getEnvironmentVariable( var ) ;
01156
01157 if ( value.empty() )
01158 {
01159 if ( htmlFormat )
01160 {
01161 variables.push_back( "<em>" + var + "</em> is not set." ) ;
01162 }
01163 else
01164 {
01165 variables.push_back( var + " is not set." ) ;
01166 }
01167 }
01168 else
01169 {
01170 if ( htmlFormat )
01171 {
01172 variables.push_back( "<b>" + var + "</b> set to ["
01173 + value + "]." ) ;
01174 }
01175 else
01176 {
01177 variables.push_back( var + " set to [" + value + "]." ) ;
01178 }
01179 }
01180
01181 }
01182
01183 return result + Ceylan::formatStringList( variables ) ;
01184
01185 #else // OSDL_USES_SDL
01186
01187 return "(not using SDL)" ;
01188
01189 #endif // OSDL_USES_SDL
01190
01191 }
01192
01193
01194
01195 bool AudioModule::IsAudioInitialized()
01196 {
01197
01198 return _AudioInitialized ;
01199
01200 }
01201
01202
01203
01204 string AudioModule::GetDriverName()
01205 {
01206
01207 #if OSDL_USES_SDL
01208
01209 char driverName[ DriverNameMaximumLength + 1 ] ;
01210
01211 if ( SDL_AudioDriverName( driverName, DriverNameMaximumLength ) == 0 )
01212 throw AudioException( "AudioModule::GetDriverName failed: "
01213 "the audio driver is probably not initialized, "
01214 "or used by another application." ) ;
01215
01216 return std::string( driverName ) ;
01217
01218 #else // OSDL_USES_SDL
01219
01220 return "unknown (not using SDL)" ;
01221
01222 #endif // OSDL_USES_SDL
01223
01224 }
01225
01226
01227
01228 void AudioModule::onMusicPlaybackFinished()
01229 {
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251 ChannelNumber AudioModule::GetChannelCountFor( ChannelFormat format )
01252 {
01253
01254 switch( format )
01255 {
01256
01257 case Mono:
01258 return 1 ;
01259 break ;
01260
01261 case Stereo:
01262 return 2 ;
01263 break ;
01264
01265 default:
01266 throw AudioException( "AudioModule::GetChannelCountFor failed: "
01267 "unknown channel format (" + Ceylan::toString( format )
01268 + ")" ) ;
01269 break ;
01270
01271 }
01272
01273 }
01274
01275
01276
01277 ChunkSize AudioModule::GetSampleSizeFor( SampleFormat format )
01278 {
01279
01280 switch( format )
01281 {
01282
01283 case Uint8SampleFormat:
01284 case Sint8SampleFormat:
01285 return 1 ;
01286 break ;
01287
01288 case LittleUint16SampleFormat:
01289 case LittleSint16SampleFormat:
01290 case BigUint16SampleFormat:
01291 case BigSint16SampleFormat:
01292
01293
01294
01295
01296
01297 return 2 ;
01298 break ;
01299
01300 default:
01301 throw AudioException( "AudioModule::GetSampleSizeFor failed: "
01302 "unknown sample format (" + Ceylan::toString( format )
01303 + ")" ) ;
01304 break ;
01305
01306 }
01307
01308 }
01309
01310
01311
01312
01313 void AudioModule::HandleMusicPlaybackFinishedCallback()
01314 {
01315
01316
01317
01318 try
01319 {
01320
01321 OSDL::Audio::getExistingAudioModule().onMusicPlaybackFinished() ;
01322
01323 }
01324 catch( const AudioException & e )
01325 {
01326
01327 LogPlug::error(
01328 "AudioModule::HandleMusicPlaybackFinishedCallback failed: "
01329 + e.toString() ) ;
01330
01331 }
01332
01333 }
01334
01335
01336
01337
01338
01339
01340
01341 AudioModule & OSDL::Audio::getExistingAudioModule()
01342 {
01343
01344 try
01345 {
01346
01347 return OSDL::getExistingCommonModule().getAudioModule() ;
01348
01349 }
01350 catch( const OSDL::Exception & e )
01351 {
01352
01353 throw AudioException( "OSDL::Audio::getExistingAudioModule: "
01354 "no audio module available: " + e.toString() ) ;
01355
01356 }
01357
01358 }
01359