File: SoundSDL2.h

package info (click to toggle)
tiatracker 1.3-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,664 kB
  • sloc: cpp: 8,875; asm: 664; makefile: 8
file content (287 lines) | stat: -rw-r--r-- 8,062 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
//============================================================================
//
//   SSSS    tt          lll  lll       
//  SS  SS   tt           ll   ll        
//  SS     tttttt  eeee   ll   ll   aaaa 
//   SSSS    tt   ee  ee  ll   ll      aa
//      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
//  SS  SS   tt   ee      ll   ll  aa  aa
//   SSSS     ttt  eeeee llll llll  aaaaa
//
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SoundSDL2.hxx 3182 2015-07-10 18:59:03Z stephena $
//============================================================================

#ifndef SOUND_SDL2_HXX
#define SOUND_SDL2_HXX

namespace Emulation {

class OSystem;

#define SDL_MAIN_HANDLED
#include <SDL.h>

#include "bspf.h"
#include "TIASnd.h"

/**
  This class implements the sound API for SDL.

  @author Stephen Anthony and Bradford W. Mott
  @version $Id: SoundSDL2.hxx 3182 2015-07-10 18:59:03Z stephena $
*/
class SoundSDL2
{
  public:
    /**
      Create a new sound object.  The init method must be invoked before
      using the object.
    */
    SoundSDL2(TIASound *tiasound);
 
    /**
      Destructor
    */
    virtual ~SoundSDL2();

  public:
    /**
      Enables/disables the sound subsystem.

      @param state  True or false, to enable or disable the sound system
    */
    void setEnabled(bool);

    /**
      The system cycle counter is being adjusting by the specified amount. Any
      members using the system cycle counter should be adjusted as needed.

      @param amount  The amount the cycle counter is being adjusted by
    */
    void adjustCycleCounter(Int32 amount);

    /**
      Sets the number of channels (mono or stereo sound).  Note that this
      determines how the emulation should 'mix' the channels of the TIA sound
      system (of which there are always two).  It does not specify the actual
      number of hardware channels that SDL should use; it will always attempt
      to use two channels in hardware.

      @param channels  The number of channels
    */
    void setChannels(uInt32 channels);

    /**
      Sets the display framerate.  Sound generation for NTSC and PAL games
      depends on the framerate, so we need to set it here.

      @param framerate The base framerate depending on NTSC or PAL ROM
    */
    void setFrameRate(float framerate);

    /**
      Initializes the sound device.  This must be called before any
      calls are made to derived methods.
    */
    void open();

    /**
      Should be called to close the sound device.  Once called the sound
      device can be started again using the open method.
    */
    void close();

    /**
      Set the mute state of the sound object.  While muted no sound is played.

      @param state  Mutes sound if true, unmute if false
    */
    void mute(bool state);

    /**
      Reset the sound device.
    */
    void reset();

    /**
      Sets the sound register to a given value.

      @param addr   The register address
      @param value  The value to save into the register
      @param cycle  The system cycle at which the register is being updated
    */
    void set(uInt16 addr, uInt8 value, Int32 cycle);

    /**
      Sets the volume of the sound device to the specified level.  The
      volume is given as a percentage from 0 to 100.  Values outside
      this range indicate that the volume shouldn't be changed at all.

      @param percent  The new volume percentage level for the sound device
    */
    void setVolume(Int32 percent);

    /**
      Adjusts the volume of the sound device based on the given direction.

      @param direction  Increase or decrease the current volume by a predefined
                        amount based on the direction (1 = increase, -1 = decrease)
    */
    void adjustVolume(Int8 direction);

  public:
    /**
      Get a descriptor for this console class (used in error checking).

      @return  The name of the object
    */
    string name() const { return "TIASound"; }

  protected:
    /**
      Invoked by the sound callback to process the next sound fragment.
      The stream is 16-bits (even though the callback is 8-bits), since
      the TIASnd class always generates signed 16-bit stereo samples.

      @param stream  Pointer to the start of the fragment
      @param length  Length of the fragment
    */
    void processFragment(Int16* stream, uInt32 length);

  protected:
    // Struct to hold information regarding a TIA sound register write
    struct RegWrite
    {
      uInt16 addr;
      uInt8 value;
      double delta;
    };

    /**
      A queue class used to hold TIA sound register writes before being
      processed while creating a sound fragment.
    */
    class RegWriteQueue
    {
      public:
        /**
          Create a new queue instance with the specified initial
          capacity.  If the queue ever reaches its capacity then it will
          automatically increase its size.
        */
        RegWriteQueue(uInt32 capacity = 512);

        virtual ~RegWriteQueue();

      public:
        /**
          Clear any items stored in the queue.
        */
        void clear();

        /**
          Dequeue the first object in the queue.
        */
        void dequeue();

        /**
          Return the duration of all the items in the queue.
        */
        double duration() const;

        /**
          Enqueue the specified object.
        */
        void enqueue(const RegWrite& info);

        /**
          Return the item at the front on the queue.

          @return  The item at the front of the queue.
        */
        RegWrite& front() const;

        /**
          Answers the number of items currently in the queue.

          @return  The number of items in the queue.
        */
        uInt32 size() const;

      private:
        // Increase the size of the queue
        void grow();

      private:
        uInt32 myCapacity;
        RegWrite *myBuffer;
        uInt32 mySize;
        uInt32 myHead;
        uInt32 myTail;

      private:
        // Following constructors and assignment operators not supported
        RegWriteQueue(const RegWriteQueue&) = delete;
        RegWriteQueue(RegWriteQueue&&) = delete;
        RegWriteQueue& operator=(const RegWriteQueue&) = delete;
        RegWriteQueue& operator=(RegWriteQueue&&) = delete;
    };

  private:
    // TIASound emulation object
    TIASound *myTIASound;

    // Indicates if the sound subsystem is to be initialized
    bool myIsEnabled;

    // Indicates if the sound device was successfully initialized
    bool myIsInitializedFlag;

    // Indicates the cycle when a sound register was last set
    Int32 myLastRegisterSetCycle;

    // Indicates the number of channels (mono or stereo)
    uInt32 myNumChannels;

    // Log base 2 of the selected fragment size
    double myFragmentSizeLogBase2;

    // The myFragmentSizeLogBase2 variable is used in only two places,
    // both of which involve an expensive division in the sound
    // processing callback
    // These are pre-computed to speed up the callback as much as possible
    double myFragmentSizeLogDiv1, myFragmentSizeLogDiv2;

    // Indicates if the sound is currently muted
    bool myIsMuted;

    // Current volume as a percentage (0 - 100)
    uInt32 myVolume;

    // Audio specification structure
    SDL_AudioSpec myHardwareSpec;

    // Queue of TIA register writes
    RegWriteQueue myRegWriteQueue;

  private:
    // Callback function invoked by the SDL Audio library when it needs data
    static void callback(void* udata, uInt8* stream, int len);

    // Following constructors and assignment operators not supported
    SoundSDL2() = delete;
    SoundSDL2(const SoundSDL2&) = delete;
    SoundSDL2(SoundSDL2&&) = delete;
    SoundSDL2& operator=(const SoundSDL2&) = delete;
    SoundSDL2& operator=(SoundSDL2&&) = delete;
};

}

#endif