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-2019 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
23class OSystem;
24class AudioQueue;
25class EmulationTiming;
26class AudioSettings;
27
28#include "SDL_lib.hxx"
29
30#include "bspf.hxx"
31#include "Sound.hxx"
32#include "audio/Resampler.hxx"
33
34/**
35 This class implements the sound API for SDL.
36
37 @author Stephen Anthony and Christian Speckner (DirtyHairy)
38*/
39class 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 virtual ~SoundSDL2();
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 Increase or decrease the current volume by a predefined
102 amount based on the direction (1 = increase, -1 = decrease)
103 */
104 void adjustVolume(Int8 direction) override;
105
106 /**
107 This method is called to provide information about the sound device.
108 */
109 string about() const override;
110
111 protected:
112 /**
113 Invoked by the sound callback to process the next sound fragment.
114 The stream is 16-bits (even though the callback is 8-bits), since
115 the TIASnd class always generates signed 16-bit stereo samples.
116
117 @param stream Pointer to the start of the fragment
118 @param length Length of the fragment
119 */
120 void processFragment(float* stream, uInt32 length);
121
122 private:
123 /**
124 The actual sound device is opened only when absolutely necessary.
125 Typically this will only happen once per program run, but it can also
126 happen dynamically when changing sample rate and/or fragment size.
127 */
128 bool openDevice();
129
130 void initResampler();
131
132 private:
133 // Indicates if the sound device was successfully initialized
134 bool myIsInitializedFlag;
135
136 // Current volume as a percentage (0 - 100)
137 uInt32 myVolume;
138 float myVolumeFactor;
139
140 // Audio specification structure
141 SDL_AudioSpec myHardwareSpec;
142
143 SDL_AudioDeviceID myDevice;
144
145 shared_ptr<AudioQueue> myAudioQueue;
146
147 EmulationTiming* myEmulationTiming;
148
149 Int16* myCurrentFragment;
150 bool myUnderrun;
151
152 unique_ptr<Resampler> myResampler;
153
154 AudioSettings& myAudioSettings;
155
156 string myAboutString;
157
158 private:
159 // Callback function invoked by the SDL Audio library when it needs data
160 static void callback(void* udata, uInt8* stream, int len);
161
162 // Following constructors and assignment operators not supported
163 SoundSDL2() = delete;
164 SoundSDL2(const SoundSDL2&) = delete;
165 SoundSDL2(SoundSDL2&&) = delete;
166 SoundSDL2& operator=(const SoundSDL2&) = delete;
167 SoundSDL2& operator=(SoundSDL2&&) = delete;
168};
169
170#endif
171
172#endif // SOUND_SUPPORT
173