1 //============================================================================ 2 // 3 // SSSS tt lll lll 4 // SS SS tt ll ll 5 // SS tttttt eeee ll ll aaaa 6 // SSSS tt ee ee ll ll aa 7 // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" 8 // SS SS tt ee ll ll aa aa 9 // SSSS ttt eeeee llll llll aaaaa 10 // 11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony 12 // and the Stella Team 13 // 14 // See the file "License.txt" for information on usage and redistribution of 15 // this file, and for a DISCLAIMER OF ALL WARRANTIES. 16 //============================================================================ 17 18 #ifdef SOUND_SUPPORT 19 20 #ifndef SOUND_SDL2_HXX 21 #define SOUND_SDL2_HXX 22 23 class OSystem; 24 class AudioQueue; 25 class EmulationTiming; 26 class AudioSettings; 27 class Resampler; 28 29 #include "SDL_lib.hxx" 30 31 #include "bspf.hxx" 32 #include "Sound.hxx" 33 34 /** 35 This class implements the sound API for SDL. 36 37 @author Stephen Anthony and Christian Speckner (DirtyHairy) 38 */ 39 class SoundSDL2 : public Sound 40 { 41 public: 42 /** 43 Create a new sound object. The init method must be invoked before 44 using the object. 45 */ 46 SoundSDL2(OSystem& osystem, AudioSettings& audioSettings); 47 48 /** 49 Destructor 50 */ 51 ~SoundSDL2() override; 52 53 public: 54 /** 55 Enables/disables the sound subsystem. 56 57 @param enable Either true or false, to enable or disable the sound system 58 */ 59 void setEnabled(bool enable) override; 60 61 /** 62 Initializes the sound device. This must be called before any 63 calls are made to derived methods. 64 */ 65 void open(shared_ptr<AudioQueue> audioQueue, EmulationTiming* emulationTiming) override; 66 67 /** 68 Should be called to close the sound device. Once called the sound 69 device can be started again using the open method. 70 */ 71 void close() override; 72 73 /** 74 Set the mute state of the sound object. While muted no sound is played. 75 76 @param state Mutes sound if true, unmute if false 77 78 @return The previous (old) mute state 79 */ 80 bool mute(bool state) override; 81 82 /** 83 Toggles the sound mute state. While muted no sound is played. 84 85 @return The previous (old) mute state 86 */ 87 bool toggleMute() override; 88 89 /** 90 Sets the volume of the sound device to the specified level. The 91 volume is given as a percentage from 0 to 100. Values outside 92 this range indicate that the volume shouldn't be changed at all. 93 94 @param percent The new volume percentage level for the sound device 95 */ 96 void setVolume(uInt32 percent) override; 97 98 /** 99 Adjusts the volume of the sound device based on the given direction. 100 101 @param direction +1 indicates increase, -1 indicates decrease. 102 */ 103 void adjustVolume(int direction = 1) override; 104 105 /** 106 This method is called to provide information about the sound device. 107 */ 108 string about() const override; 109 110 protected: 111 /** 112 This method is called to query the audio devices. 113 114 @param devices List of device names 115 */ 116 void queryHardware(VariantList& devices) override; 117 118 /** 119 Invoked by the sound callback to process the next sound fragment. 120 The stream is 16-bits (even though the callback is 8-bits), since 121 the TIASnd class always generates signed 16-bit stereo samples. 122 123 @param stream Pointer to the start of the fragment 124 @param length Length of the fragment 125 */ 126 void processFragment(float* stream, uInt32 length); 127 128 private: 129 /** 130 The actual sound device is opened only when absolutely necessary. 131 Typically this will only happen once per program run, but it can also 132 happen dynamically when changing sample rate and/or fragment size. 133 */ 134 bool openDevice(); 135 136 void initResampler(); 137 138 private: 139 // Indicates if the sound device was successfully initialized 140 bool myIsInitializedFlag{false}; 141 142 // Current volume as a percentage (0 - 100) 143 uInt32 myVolume{100}; 144 float myVolumeFactor{0xffff}; 145 146 // Audio specification structure 147 SDL_AudioSpec myHardwareSpec; 148 149 uInt32 myDeviceId{0}; 150 151 SDL_AudioDeviceID myDevice{0}; 152 153 shared_ptr<AudioQueue> myAudioQueue; 154 155 EmulationTiming* myEmulationTiming{nullptr}; 156 157 Int16* myCurrentFragment{nullptr}; 158 bool myUnderrun{false}; 159 160 unique_ptr<Resampler> myResampler; 161 162 AudioSettings& myAudioSettings; 163 164 string myAboutString; 165 166 private: 167 // Callback function invoked by the SDL Audio library when it needs data 168 static void callback(void* udata, uInt8* stream, int len); 169 170 // Following constructors and assignment operators not supported 171 SoundSDL2() = delete; 172 SoundSDL2(const SoundSDL2&) = delete; 173 SoundSDL2(SoundSDL2&&) = delete; 174 SoundSDL2& operator=(const SoundSDL2&) = delete; 175 SoundSDL2& operator=(SoundSDL2&&) = delete; 176 }; 177 178 #endif 179 180 #endif // SOUND_SUPPORT 181