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 {
00335
00336 send( "Initializing audio subsystem." ) ;
00337
00338 #if OSDL_USES_SDL
00339
00340 if ( SDL_InitSubSystem(
00341 CommonModule::UseAudio ) != CommonModule::BackendSuccess )
00342 throw AudioException( "AudioModule constructor: "
00343 "unable to initialize audio subsystem: "
00344 + Utils::getBackendLastError() ) ;
00345
00346 #if OSDL_USES_SDL_MIXER
00347
00348 SDL_version compileTimeSDLMixerVersion ;
00349 MIX_VERSION( & compileTimeSDLMixerVersion ) ;
00350
00351 SDL_version linkTimeSDLMixerVersion = *Mix_Linked_Version() ;
00352
00353
00354
00355 ::Mix_HookMusicFinished( HandleMusicPlaybackFinishedCallback ) ;
00356
00357
00358 send( "Using SDL_mixer backend, compiled against the "
00359 + Ceylan::toNumericalString( compileTimeSDLMixerVersion.major) + "."
00360 + Ceylan::toNumericalString( compileTimeSDLMixerVersion.minor) + "."
00361 + Ceylan::toNumericalString( compileTimeSDLMixerVersion.patch)
00362 + " version, linked against the "
00363 + Ceylan::toNumericalString( linkTimeSDLMixerVersion.major) + "."
00364 + Ceylan::toNumericalString( linkTimeSDLMixerVersion.minor) + "."
00365 + Ceylan::toNumericalString( linkTimeSDLMixerVersion.patch)
00366 + " version." ) ;
00367
00368
00369 if ( _controlMusicManager )
00370 {
00371
00372 if ( MusicManager::_CurrentMusicManager != 0 )
00373 throw AudioException( "AudioModule constructor failed: "
00374 "there is already a music manager registered." ) ;
00375
00376 MusicManager::_CurrentMusicManager = new MusicManager() ;
00377
00378 }
00379
00380 #endif // OSDL_USES_SDL_MIXER
00381
00382
00383 #else // OSDL_USES_SDL
00384
00385 #if OSDL_ARCH_NINTENDO_DS
00386
00387
00388 #ifdef OSDL_RUNS_ON_ARM7
00389
00390
00391
00392 #elif defined(OSDL_RUNS_ON_ARM9)
00393
00394 CommandManager::GetCommandManager().enableMusicSupport() ;
00395
00396 #endif // OSDL_RUNS_ON_ARM7
00397
00398
00399
00400 #endif // OSDL_ARCH_NINTENDO_DS
00401
00402 #endif // OSDL_USES_SDL
00403
00404 _AudioInitialized = true ;
00405
00406
00407 send( "Audio subsystem initialized." ) ;
00408
00409 dropIdentifier() ;
00410
00411 }
00412
00413
00414
00415 AudioModule::~AudioModule() throw()
00416 {
00417
00418 send( "Stopping audio subsystem." ) ;
00419
00420 if ( _controlMusicManager )
00421 {
00422
00423 if ( MusicManager::_CurrentMusicManager != 0 )
00424 {
00425
00426 delete MusicManager::_CurrentMusicManager ;
00427 MusicManager::_CurrentMusicManager = 0 ;
00428
00429 }
00430 else
00431 {
00432
00433 LogPlug::error( "AudioModule destructor: "
00434 "no music manager found." ) ;
00435
00436 }
00437
00438 }
00439
00440
00441 if ( _mixerInitialized )
00442 {
00443
00444 try
00445 {
00446
00447 unsetMode() ;
00448
00449 }
00450 catch( const AudioException & e )
00451 {
00452
00453 LogPlug::error( "AudioModule destructor: "
00454 "unsetting of the mixer failed: " + e.toString() ) ;
00455 }
00456
00457 }
00458
00459
00460 #if OSDL_USES_SDL
00461
00462 SDL_QuitSubSystem( CommonModule::UseAudio ) ;
00463
00464 #else // OSDL_USES_SDL
00465
00466 #if OSDL_ARCH_NINTENDO_DS
00467
00468
00469 #ifdef OSDL_RUNS_ON_ARM7
00470
00471 #elif defined(OSDL_RUNS_ON_ARM9)
00472
00473 #endif // OSDL_RUNS_ON_ARM7
00474
00475 #endif // OSDL_ARCH_NINTENDO_DS
00476
00477 #endif // OSDL_USES_SDL
00478
00479 _AudioInitialized = false ;
00480
00481 send( "Audio subsystem stopped." ) ;
00482
00483 }
00484
00485
00486
00487 void AudioModule::setMode( Hertz outputFrequency,
00488 SampleFormat outputSampleFormat, ChannelFormat outputChannel,
00489 ChunkSize outputBufferSize, ChannelNumber mixingChannelCount )
00490 {
00491
00492 #if OSDL_USES_SDL_MIXER
00493
00494 if ( _mixerInitialized )
00495 throw AudioException( "AudioModule::setMode failed: "
00496 "mixing mode already set, and not unset yet" ) ;
00497
00498 if ( ::Mix_OpenAudio( outputFrequency, outputSampleFormat,
00499 GetChannelCountFor( outputChannel ), outputBufferSize ) != 0 )
00500 throw AudioException( "AudioModule::setMode failed: "
00501 + string( ::Mix_GetError() )
00502 + ". Maybe the audio driver is used by another application?" ) ;
00503
00504 _chunkSize = outputBufferSize ;
00505
00506 ChannelNumber channelCount = ::Mix_AllocateChannels( mixingChannelCount ) ;
00507
00508 if ( channelCount != mixingChannelCount )
00509 throw AudioException( "AudioModule::setMode: wanted "
00510 + Ceylan::toString( mixingChannelCount )
00511 + " input mixing channel(s), but got "
00512 + Ceylan::toString( _inputChannels.size() )
00513 + " channel(s) instead" ) ;
00514
00515 try
00516 {
00517
00518 for ( ChannelNumber i = 0; i < channelCount; i++ )
00519 _inputChannels.push_back( new AudioChannel( i ) ) ;
00520
00521 }
00522 catch( const AudioChannelException & e )
00523 {
00524
00525 throw AudioException(
00526 "AudioModule::setMode failed when creating mixing channels: "
00527 + e.toString() ) ;
00528
00529 }
00530
00531 _mixerInitialized = true ;
00532
00533 #else // OSDL_USES_SDL_MIXER
00534
00535 throw AudioException( "AudioModule::setMode failed: "
00536 "no SDL_mixer support available" ) ;
00537
00538 #endif // OSDL_USES_SDL_MIXER
00539
00540 }
00541
00542
00543
00544 Ceylan::System::Millisecond AudioModule::getObtainedMode(
00545 Hertz & actualOutputFrequency, SampleFormat & actualOutputSampleFormat,
00546 ChannelNumber & actualOutputChannelCount )
00547 {
00548
00549 #if OSDL_USES_SDL_MIXER
00550
00551
00552 int channelNumber, frequency ;
00553
00554 if ( ::Mix_QuerySpec( & frequency, & actualOutputSampleFormat,
00555 & channelNumber ) == 0 )
00556 throw AudioException( " AudioModule::getObtainedMode failed: "
00557 + string( ::Mix_GetError() ) ) ;
00558
00559 actualOutputChannelCount = channelNumber ;
00560 actualOutputFrequency = frequency ;
00561
00562
00563 return static_cast<Ceylan::System::Millisecond>(
00564 1000.0f / 2 * _chunkSize /
00565 ( actualOutputFrequency * actualOutputChannelCount
00566 * GetSampleSizeFor( actualOutputSampleFormat ) ) ) ;
00567
00568 #else // OSDL_USES_SDL_MIXER
00569
00570 throw AudioException( "AudioModule::getObtainedMode failed: "
00571 "no SDL_mixer support available" ) ;
00572
00573 #endif // OSDL_USES_SDL_MIXER
00574
00575 }
00576
00577
00578
00579 void AudioModule::unsetMode()
00580 {
00581
00582 #if OSDL_USES_SDL_MIXER
00583
00584 if ( _mixerInitialized )
00585 {
00586
00587 ::Mix_CloseAudio() ;
00588 _mixerInitialized = false ;
00589 _chunkSize = 0 ;
00590
00591 for ( vector<AudioChannel *>::iterator it = _inputChannels.begin();
00592 it != _inputChannels.end(); it++ )
00593 delete (*it) ;
00594
00595 _inputChannels.clear() ;
00596
00597 }
00598 else
00599 {
00600
00601 LOG_WARNING_AUDIO( "AudioModule::unsetMode called "
00602 "whereas not already initialized, nothing done." ) ;
00603
00604 }
00605
00606 #else // OSDL_USES_SDL_MIXER
00607
00608 throw AudioException( "AudioModule::unsetMode failed: "
00609 "no SDL_mixer support available" ) ;
00610
00611 #endif // OSDL_USES_SDL_MIXER
00612
00613 }
00614
00615
00616
00617 void AudioModule::setPanning( Ceylan::Maths::Percentage leftPercentage )
00618 {
00619
00620 #if OSDL_USES_SDL_MIXER
00621
00622 Ceylan::Uint8 left = static_cast<Ceylan::Uint8>(
00623 ( leftPercentage * 254 ) / 100 ) ;
00624
00625 if ( ::Mix_SetPanning( MIX_CHANNEL_POST, left,
00626 254 - left ) == 0 )
00627 throw AudioException( "AudioModule::setPanning failed: "
00628 + string( ::Mix_GetError() ) ) ;
00629
00630 #else // OSDL_USES_SDL_MIXER
00631
00632 throw AudioException( "AudioModule::setPanning failed: "
00633 "no SDL_mixer support available" ) ;
00634
00635 #endif // OSDL_USES_SDL_MIXER
00636
00637 }
00638
00639
00640
00641 void AudioModule::unsetPanning()
00642 {
00643
00644 #if OSDL_USES_SDL_MIXER
00645
00646 if ( ::Mix_SetPanning( MIX_CHANNEL_POST, 255,
00647 255 ) == 0 )
00648 throw AudioException( "AudioModule::unsetPanning failed: "
00649 + string( ::Mix_GetError() ) ) ;
00650
00651 #else // OSDL_USES_SDL_MIXER
00652
00653 throw AudioException( "AudioModule::unsetPanning failed: "
00654 "no SDL_mixer support available" ) ;
00655
00656 #endif // OSDL_USES_SDL_MIXER
00657
00658 }
00659
00660
00661
00662 void AudioModule::setReverseStereo( bool reverse )
00663 {
00664
00665 #if OSDL_USES_SDL_MIXER
00666
00667 if ( ::Mix_SetReverseStereo( MIX_CHANNEL_POST,
00668 ( ( reverse == true ) ? 1 : 0 ) ) == 0 )
00669 throw AudioException( "AudioModule::setReverseStereo failed: "
00670 + string( ::Mix_GetError() ) ) ;
00671
00672 #else // OSDL_USES_SDL_MIXER
00673
00674 throw AudioException( "AudioModule::setReverseStereo failed: "
00675 "no SDL_mixer support available" ) ;
00676
00677 #endif // OSDL_USES_SDL_MIXER
00678
00679 }
00680
00681
00682
00683 void AudioModule::setDistanceAttenuation( ListenerDistance distance )
00684 {
00685
00686 #if OSDL_USES_SDL_MIXER
00687
00688 if ( ::Mix_SetDistance( MIX_CHANNEL_POST, distance )
00689 == 0 )
00690 throw AudioException( "AudioModule::setDistanceAttenuation failed: "
00691 + string( ::Mix_GetError() ) ) ;
00692
00693 #else // OSDL_USES_SDL_MIXER
00694
00695 throw AudioException( "AudioModule::setDistanceAttenuation failed: "
00696 "no SDL_mixer support available" ) ;
00697
00698 #endif // OSDL_USES_SDL_MIXER
00699
00700 }
00701
00702
00703
00704 void AudioModule::unsetDistanceAttenuation()
00705 {
00706
00707 #if OSDL_USES_SDL_MIXER
00708
00709 if ( ::Mix_SetDistance( MIX_CHANNEL_POST, 0 ) == 0 )
00710 throw AudioException( "AudioModule::unsetDistanceAttenuation failed: "
00711 + string( ::Mix_GetError() ) ) ;
00712
00713 #else // OSDL_USES_SDL_MIXER
00714
00715 throw AudioException( "AudioModule::unsetDistanceAttenuation failed: "
00716 "no SDL_mixer support available" ) ;
00717
00718 #endif // OSDL_USES_SDL_MIXER
00719
00720 }
00721
00722
00723
00724 void AudioModule::setPositionAttenuation( ListenerDistance distance,
00725 ListenerAngle angle )
00726 {
00727
00728 #if OSDL_USES_SDL_MIXER
00729
00730 if ( ::Mix_SetPosition( MIX_CHANNEL_POST,
00731 distance, angle ) == 0 )
00732 throw AudioException( "AudioModule::setPositionAttenuation failed: "
00733 + string( ::Mix_GetError() ) ) ;
00734
00735 #else // OSDL_USES_SDL_MIXER
00736
00737 throw AudioException( "AudioModule::setPositionAttenuation failed: "
00738 "no SDL_mixer support available" ) ;
00739
00740 #endif // OSDL_USES_SDL_MIXER
00741
00742 }
00743
00744
00745
00746 void AudioModule::unsetPositionAttenuation()
00747 {
00748
00749 #if OSDL_USES_SDL_MIXER
00750
00751 if ( ::Mix_SetPosition( MIX_CHANNEL_POST, 0, 0 ) == 0 )
00752 throw AudioException( "AudioModule::unsetPositionAttenuation failed: "
00753 + string( ::Mix_GetError() ) ) ;
00754
00755 #else // OSDL_USES_SDL_MIXER
00756
00757 throw AudioException( "AudioModule::unsetPositionAttenuation failed: "
00758 "no SDL_mixer support available" ) ;
00759
00760 #endif // OSDL_USES_SDL_MIXER
00761
00762 }
00763
00764
00765
00766 MusicType AudioModule::getTypeOfCurrentMusic() const
00767 {
00768
00769 #if OSDL_USES_SDL_MIXER
00770
00771 return Music::GetTypeOf( 0 ) ;
00772
00773 #else // OSDL_USES_SDL_MIXER
00774
00775 throw AudioException( "AudioModule::getTypeOfCurrentMusic failed: "
00776 "no SDL_mixer support available" ) ;
00777
00778 #endif // OSDL_USES_SDL_MIXER
00779
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792 ChannelNumber AudioModule::getMixingChannelCount() const
00793 {
00794
00795 #if OSDL_USES_SDL_MIXER
00796
00797 #if OSDL_DEBUG
00798
00799 if ( ::Mix_AllocateChannels( -1 ) !=
00800 static_cast<int>( _inputChannels.size() ) )
00801 throw AudioException( "AudioModule::getMixingChannelCount failed: "
00802 "inconsistency in channel count" ) ;
00803
00804 #endif // OSDL_DEBUG
00805
00806
00807 return ::Mix_AllocateChannels( -1 ) ;
00808
00809 #else // OSDL_USES_SDL_MIXER
00810
00811 throw AudioException( "AudioModule::getMixingChannelCount failed: "
00812 "no SDL_mixer support available" ) ;
00813
00814 #endif // OSDL_USES_SDL_MIXER
00815
00816 }
00817
00818
00819
00820 AudioChannel & AudioModule::getMixingChannelAt( ChannelNumber index ) const
00821 {
00822
00823 try
00824 {
00825
00826 return *_inputChannels.at( index ) ;
00827
00828 }
00829 catch( const std::exception & e )
00830 {
00831
00832 throw AudioException( "AudioModule::getMixingChannelAt out of bounds: "
00833 + string( e.what() ) ) ;
00834 }
00835
00836 }
00837
00838
00839
00840 void AudioModule::setVolumeForAllMixingChannels( Volume newVolume )
00841 {
00842
00843 #if OSDL_USES_SDL_MIXER
00844
00845 ::Mix_Volume( -1, newVolume ) ;
00846
00847 #else // OSDL_USES_SDL_MIXER
00848
00849 throw AudioException( "AudioModule::setVolumeForAllMixingChannels failed: "
00850 "no SDL_mixer support available" ) ;
00851
00852 #endif // OSDL_USES_SDL_MIXER
00853
00854 }
00855
00856
00857
00858 ChannelNumber AudioModule::getPlayingChannelCount() const
00859 {
00860
00861 #if OSDL_USES_SDL_MIXER
00862
00863 return ::Mix_Playing( -1 ) ;
00864
00865 #else // OSDL_USES_SDL_MIXER
00866
00867 throw AudioException( "AudioModule::getPlayingChannelCount failed: "
00868 "no SDL_mixer support available" ) ;
00869
00870 #endif // OSDL_USES_SDL_MIXER
00871
00872 }
00873
00874
00875
00876 ChannelNumber AudioModule::getPausedChannelCount() const
00877 {
00878
00879 #if OSDL_USES_SDL_MIXER
00880
00881 return ::Mix_Paused( -1 ) ;
00882
00883 #else // OSDL_USES_SDL_MIXER
00884
00885 throw AudioException( "AudioModule::getPausedChannelCount failed: "
00886 "no SDL_mixer support available" ) ;
00887
00888 #endif // OSDL_USES_SDL_MIXER
00889
00890 }
00891
00892
00893
00894 void AudioModule::pauseAllChannels()
00895 {
00896
00897 #if OSDL_USES_SDL_MIXER
00898
00899 ::Mix_Pause( -1 ) ;
00900
00901 #else // OSDL_USES_SDL_MIXER
00902
00903 throw AudioException( "AudioModule::pauseAllChannels failed: "
00904 "no SDL_mixer support available" ) ;
00905
00906 #endif // OSDL_USES_SDL_MIXER
00907
00908 }
00909
00910
00911
00912 void AudioModule::resumeAllChannels()
00913 {
00914
00915 #if OSDL_USES_SDL_MIXER
00916
00917 ::Mix_Resume( -1 ) ;
00918
00919 #else // OSDL_USES_SDL_MIXER
00920
00921 throw AudioException( "AudioModule::resumeAllChannels failed: "
00922 "no SDL_mixer support available" ) ;
00923
00924 #endif // OSDL_USES_SDL_MIXER
00925
00926 }
00927
00928
00929
00930 void AudioModule::haltAllChannels()
00931 {
00932
00933 #if OSDL_USES_SDL_MIXER
00934
00935 ::Mix_HaltChannel( -1 ) ;
00936
00937 #else // OSDL_USES_SDL_MIXER
00938
00939 throw AudioException( "AudioModule::haltAllChannels failed: "
00940 "no SDL_mixer support available" ) ;
00941
00942 #endif // OSDL_USES_SDL_MIXER
00943
00944 }
00945
00946
00947
00948 ChannelNumber AudioModule::expireAllChannelsIn(
00949 Ceylan::System::Millisecond expireDuration )
00950 {
00951
00952 #if OSDL_USES_SDL_MIXER
00953
00954 return ::Mix_ExpireChannel( -1, expireDuration ) ;
00955
00956 #else // OSDL_USES_SDL_MIXER
00957
00958 throw AudioException( "AudioModule::expireAllChannelsIn failed: "
00959 "no SDL_mixer support available" ) ;
00960
00961 #endif // OSDL_USES_SDL_MIXER
00962
00963 }
00964
00965
00966
00967 ChannelNumber AudioModule::fadeOutAllChannelsDuring(
00968 Ceylan::System::Millisecond fadeOutDuration )
00969 {
00970
00971 #if OSDL_USES_SDL_MIXER
00972
00973 return ::Mix_FadeOutChannel( -1, fadeOutDuration ) ;
00974
00975 #else // OSDL_USES_SDL_MIXER
00976
00977 throw AudioException( "AudioModule::fadeOutAllChannelsDuring failed: "
00978 "no SDL_mixer support available" ) ;
00979
00980 #endif // OSDL_USES_SDL_MIXER
00981
00982 }
00983
00984
00985
00986 bool AudioModule::isMusicPlaying() const
00987 {
00988
00989 #if OSDL_USES_SDL_MIXER
00990
00991 return ( ::Mix_PlayingMusic() == 1 ) ; ;
00992
00993 #else // OSDL_USES_SDL_MIXER
00994
00995 throw AudioException( "AudioModule::isMusicPlaying failed: "
00996 "no SDL_mixer support available" ) ;
00997
00998 #endif // OSDL_USES_SDL_MIXER
00999
01000 }
01001
01002
01003
01004 bool AudioModule::isMusicPaused() const
01005 {
01006
01007 #if OSDL_USES_SDL_MIXER
01008
01009 return ( ::Mix_PausedMusic() == 1 ) ; ;
01010
01011 #else // OSDL_USES_SDL_MIXER
01012
01013 throw AudioException( "AudioModule::isMusicPaused failed: "
01014 "no SDL_mixer support available" ) ;
01015
01016 #endif // OSDL_USES_SDL_MIXER
01017
01018 }
01019
01020
01021
01022 FadingStatus AudioModule::getMusicFadingStatus() const
01023 {
01024
01025 #if OSDL_USES_SDL_MIXER
01026
01027 switch( ::Mix_FadingMusic() )
01028 {
01029
01030 case MIX_NO_FADING:
01031 return None ;
01032 break ;
01033
01034 case MIX_FADING_OUT:
01035 return Out ;
01036 break ;
01037
01038 case MIX_FADING_IN:
01039 return In ;
01040 break ;
01041
01042 default:
01043 LogPlug::error(
01044 " AudioModule::getMusicFadingStatus: unexpected status" ) ;
01045 return None ;
01046 break ;
01047
01048 }
01049
01050 #else // OSDL_USES_SDL_MIXER
01051
01052 throw AudioException( "AudioModule::getMusicFadingStatus failed: "
01053 "no SDL_mixer support available" ) ;
01054
01055 #endif // OSDL_USES_SDL_MIXER
01056
01057 }
01058
01059
01060
01061 std::string AudioModule::getDriverName() const
01062 {
01063
01064 return AudioModule::GetDriverName() ;
01065
01066 }
01067
01068
01069
01070 const string AudioModule::toString( Ceylan::VerbosityLevels level ) const
01071 {
01072
01073
01074 string res = "Audio module, " ;
01075
01076 if ( ! _mixerInitialized )
01077 {
01078
01079 res += "mixer not initialized" ;
01080
01081 }
01082 else
01083 {
01084
01085 res += "mixer is initialized. Chunk size is "
01086 + Ceylan::toString( _chunkSize )
01087 + " bytes. There are " + Ceylan::toString( _inputChannels.size() )
01088 + " input mixing channel(s)" ;
01089
01090 }
01091
01092 if ( level == Ceylan::low )
01093 return res ;
01094
01095 res += ". " + Ceylan::Module::toString() ;
01096
01097 return res ;
01098
01099 }
01100
01101
01102
01103 string AudioModule::DescribeEnvironmentVariables()
01104 {
01105
01106 #if OSDL_USES_SDL
01107
01108 Ceylan::Uint16 varCount =
01109 sizeof( SDLEnvironmentVariables ) / sizeof (string) ;
01110
01111 string result = "Examining the " + Ceylan::toString( varCount )
01112 + " audio-related environment variables for SDL backend:" ;
01113
01114 list<string> variables ;
01115
01116 string var, value ;
01117
01118 TextOutputFormat htmlFormat = Ceylan::TextDisplayable::GetOutputFormat() ;
01119
01120 for ( Ceylan::Uint16 i = 0; i < varCount; i++ )
01121 {
01122 var = SDLEnvironmentVariables[ i ] ;
01123 value = Ceylan::System::getEnvironmentVariable( var ) ;
01124
01125 if ( value.empty() )
01126 {
01127 if ( htmlFormat )
01128 {
01129 variables.push_back( "<em>" + var + "</em> is not set." ) ;
01130 }
01131 else
01132 {
01133 variables.push_back( var + " is not set." ) ;
01134 }
01135 }
01136 else
01137 {
01138 if ( htmlFormat )
01139 {
01140 variables.push_back( "<b>" + var + "</b> set to ["
01141 + value + "]." ) ;
01142 }
01143 else
01144 {
01145 variables.push_back( var + " set to [" + value + "]." ) ;
01146 }
01147 }
01148
01149 }
01150
01151 return result + Ceylan::formatStringList( variables ) ;
01152
01153 #else // OSDL_USES_SDL
01154
01155 return "(not using SDL)" ;
01156
01157 #endif // OSDL_USES_SDL
01158
01159 }
01160
01161
01162
01163 bool AudioModule::IsAudioInitialized()
01164 {
01165
01166 return _AudioInitialized ;
01167
01168 }
01169
01170
01171
01172 string AudioModule::GetDriverName()
01173 {
01174
01175 #if OSDL_USES_SDL
01176
01177 char driverName[ DriverNameMaximumLength + 1 ] ;
01178
01179 if ( SDL_AudioDriverName( driverName, DriverNameMaximumLength ) == 0 )
01180 throw AudioException( "AudioModule::GetDriverName failed: "
01181 "the audio driver is probably not initialized, "
01182 "or used by another application." ) ;
01183
01184 return std::string( driverName ) ;
01185
01186 #else // OSDL_USES_SDL
01187
01188 return "unknown (not using SDL)" ;
01189
01190 #endif // OSDL_USES_SDL
01191
01192 }
01193
01194
01195
01196 void AudioModule::onMusicPlaybackFinished()
01197 {
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219 ChannelNumber AudioModule::GetChannelCountFor( ChannelFormat format )
01220 {
01221
01222 switch( format )
01223 {
01224
01225 case Mono:
01226 return 1 ;
01227 break ;
01228
01229 case Stereo:
01230 return 2 ;
01231 break ;
01232
01233 default:
01234 throw AudioException( "AudioModule::GetChannelCountFor failed: "
01235 "unknown channel format (" + Ceylan::toString( format )
01236 + ")" ) ;
01237 break ;
01238
01239 }
01240
01241 }
01242
01243
01244
01245 ChunkSize AudioModule::GetSampleSizeFor( SampleFormat format )
01246 {
01247
01248 switch( format )
01249 {
01250
01251 case Uint8SampleFormat:
01252 case Sint8SampleFormat:
01253 return 1 ;
01254 break ;
01255
01256 case LittleUint16SampleFormat:
01257 case LittleSint16SampleFormat:
01258 case BigUint16SampleFormat:
01259 case BigSint16SampleFormat:
01260
01261
01262
01263
01264
01265 return 2 ;
01266 break ;
01267
01268 default:
01269 throw AudioException( "AudioModule::GetSampleSizeFor failed: "
01270 "unknown sample format (" + Ceylan::toString( format )
01271 + ")" ) ;
01272 break ;
01273
01274 }
01275
01276 }
01277
01278
01279
01280
01281 void AudioModule::HandleMusicPlaybackFinishedCallback()
01282 {
01283
01284
01285
01286 try
01287 {
01288
01289 OSDL::Audio::getExistingAudioModule().onMusicPlaybackFinished() ;
01290
01291 }
01292 catch( const AudioException & e )
01293 {
01294
01295 LogPlug::error(
01296 "AudioModule::HandleMusicPlaybackFinishedCallback failed: "
01297 + e.toString() ) ;
01298
01299 }
01300
01301 }
01302
01303
01304
01305
01306
01307
01308
01309 AudioModule & OSDL::Audio::getExistingAudioModule()
01310 {
01311
01312 try
01313 {
01314
01315 return OSDL::getExistingCommonModule().getAudioModule() ;
01316
01317 }
01318 catch( const OSDL::Exception & e )
01319 {
01320
01321 throw AudioException( "OSDL::Audio::getExistingAudioModule: "
01322 "no audio module available: " + e.toString() ) ;
01323
01324 }
01325
01326 }
01327