1 /* internal-only header
2  * Updated for 4.9 api inclusion by Ryan Dickie
3  * Originally done by KC/Milan
4  */
5 #ifndef AINTERN_AUDIO_H
6 #define AINTERN_AUDIO_H
7 
8 #include "allegro5/allegro.h"
9 #include "allegro5/internal/aintern_list.h"
10 #include "allegro5/internal/aintern_vector.h"
11 #include "../allegro_audio.h"
12 
13 struct ALLEGRO_AUDIO_RECORDER {
14   ALLEGRO_EVENT_SOURCE source;
15 
16   ALLEGRO_THREAD           *thread;
17   ALLEGRO_MUTEX            *mutex;
18   ALLEGRO_COND             *cond;
19                            /* recording is done in its own thread as
20                               implemented by the driver */
21 
22   ALLEGRO_AUDIO_DEPTH      depth;
23   ALLEGRO_CHANNEL_CONF     chan_conf;
24   unsigned int             frequency;
25 
26   void                     **fragments;
27                            /* the buffers to record into */
28 
29   unsigned int             fragment_count;
30                            /* the number of fragments */
31 
32   unsigned int             samples;
33                            /* the number of samples returned at every FRAGMENT event */
34 
35   size_t                   fragment_size;
36                            /* size in bytes of each fragument */
37 
38   unsigned int             sample_size;
39                            /* the size in bytes of each sample */
40 
41   volatile bool            is_recording;
42                            /* true if the driver should actively be updating
43                               the buffer */
44 
45   void                     *extra;
46                            /* custom data for the driver to use as needed */
47 };
48 
49 typedef enum ALLEGRO_AUDIO_DRIVER_ENUM
50 {
51    /* Various driver modes. */
52    ALLEGRO_AUDIO_DRIVER_AUTODETECT = 0x20000,
53    ALLEGRO_AUDIO_DRIVER_OPENAL     = 0x20001,
54    ALLEGRO_AUDIO_DRIVER_ALSA       = 0x20002,
55    ALLEGRO_AUDIO_DRIVER_DSOUND     = 0x20003,
56    ALLEGRO_AUDIO_DRIVER_OSS        = 0x20004,
57    ALLEGRO_AUDIO_DRIVER_AQUEUE     = 0x20005,
58    ALLEGRO_AUDIO_DRIVER_PULSEAUDIO = 0x20006,
59    ALLEGRO_AUDIO_DRIVER_OPENSL     = 0x20007,
60    ALLEGRO_AUDIO_DRIVER_SDL        = 0x20008
61 } ALLEGRO_AUDIO_DRIVER_ENUM;
62 
63 typedef struct ALLEGRO_AUDIO_DRIVER ALLEGRO_AUDIO_DRIVER;
64 struct ALLEGRO_AUDIO_DRIVER {
65    const char     *specifier;
66 
67    int            (*open)(void);
68    void           (*close)(void);
69 
70    int            (*allocate_voice)(ALLEGRO_VOICE*);
71    void           (*deallocate_voice)(ALLEGRO_VOICE*);
72 
73    int            (*load_voice)(ALLEGRO_VOICE*, const void*);
74    void           (*unload_voice)(ALLEGRO_VOICE*);
75 
76    int            (*start_voice)(ALLEGRO_VOICE*);
77    int            (*stop_voice)(ALLEGRO_VOICE*);
78 
79    bool           (*voice_is_playing)(const ALLEGRO_VOICE*);
80 
81    unsigned int   (*get_voice_position)(const ALLEGRO_VOICE*);
82    int            (*set_voice_position)(ALLEGRO_VOICE*, unsigned int);
83 
84 
85    int            (*allocate_recorder)(struct ALLEGRO_AUDIO_RECORDER *);
86    void           (*deallocate_recorder)(struct ALLEGRO_AUDIO_RECORDER *);
87 };
88 
89 extern ALLEGRO_AUDIO_DRIVER *_al_kcm_driver;
90 
91 const void *_al_voice_update(ALLEGRO_VOICE *voice, ALLEGRO_MUTEX *mutex,
92    unsigned int *samples);
93 bool _al_kcm_set_voice_playing(ALLEGRO_VOICE *voice, ALLEGRO_MUTEX *mutex,
94    bool val);
95 
96 /* A voice structure that you'd attach a mixer or sample to. Ideally there
97  * would be one ALLEGRO_VOICE per system/hardware voice.
98  */
99 struct ALLEGRO_VOICE {
100    ALLEGRO_AUDIO_DEPTH  depth;
101    ALLEGRO_CHANNEL_CONF chan_conf;
102 
103    unsigned int         frequency;
104 
105    size_t               buffer_size;
106    size_t               num_buffers;
107                         /* If non-0, they must be honored by the driver. */
108 
109    ALLEGRO_SAMPLE_INSTANCE       *attached_stream;
110                         /* The stream that is attached to the voice, or NULL.
111                          * May be an ALLEGRO_SAMPLE_INSTANCE or ALLEGRO_MIXER object.
112                          */
113 
114    bool                 is_streaming;
115                         /* True for voices with an attached mixer. */
116 
117    ALLEGRO_MUTEX        *mutex;
118    ALLEGRO_COND         *cond;
119 
120    _AL_LIST_ITEM        *dtor_item;
121 
122    ALLEGRO_AUDIO_DRIVER *driver;
123                         /* XXX shouldn't there only be one audio driver active
124                          * at a time?
125                          */
126 
127    void                 *extra;
128                         /* Extra data for use by the driver. */
129 };
130 
131 
132 typedef union {
133    float    *f32;
134    uint32_t *u24;
135    int32_t  *s24;
136    uint16_t *u16;
137    int16_t  *s16;
138    uint8_t  *u8;
139    int8_t   *s8;
140    void     *ptr;
141 } any_buffer_t;
142 
143 struct ALLEGRO_SAMPLE {
144    ALLEGRO_AUDIO_DEPTH  depth;
145    ALLEGRO_CHANNEL_CONF chan_conf;
146    unsigned int         frequency;
147    int                  len;
148    any_buffer_t         buffer;
149    bool                 free_buf;
150                         /* Whether `buffer' needs to be freed when the sample
151                          * is destroyed, or when `buffer' changes.
152                          */
153    _AL_LIST_ITEM        *dtor_item;
154 };
155 
156 /* Read some samples into a mixer buffer.
157  *
158  * source:
159  *    The object to read samples from.  This may be one of several types.
160  *
161  * *vbuf: (in-out parameter)
162  *    Pointer to pointer to destination buffer.
163  *    (should confirm what it means to change the pointer on return)
164  *
165  * *samples: (in-out parameter)
166  *    On input indicates the maximum number of samples that can fit into *vbuf.
167  *    On output indicates the actual number of samples that were read.
168  *
169  * buffer_depth:
170  *    The audio depth of the destination buffer.
171  *
172  * dest_maxc:
173  *    The number of channels in the destination.
174  */
175 typedef void (*stream_reader_t)(void *source, void **vbuf,
176    unsigned int *samples, ALLEGRO_AUDIO_DEPTH buffer_depth, size_t dest_maxc);
177 
178 typedef struct {
179    union {
180       ALLEGRO_MIXER     *mixer;
181       ALLEGRO_VOICE     *voice;
182       void              *ptr;
183    } u;
184    bool                 is_voice;
185 } sample_parent_t;
186 
187 /* The sample struct also serves the base of ALLEGRO_AUDIO_STREAM, ALLEGRO_MIXER. */
188 struct ALLEGRO_SAMPLE_INSTANCE {
189    /* ALLEGRO_SAMPLE_INSTANCE does not generate any events yet but ALLEGRO_AUDIO_STREAM
190     * does, which can inherit only ALLEGRO_SAMPLE_INSTANCE. */
191    ALLEGRO_EVENT_SOURCE es;
192 
193    ALLEGRO_SAMPLE       spl_data;
194 
195    volatile bool        is_playing;
196                         /* Is this sample is playing? */
197 
198    ALLEGRO_PLAYMODE     loop;
199    float                speed;
200    float                gain;
201    float                pan;
202 
203    /* When resampling an audio stream there will be fractional sample
204     * positions due to the difference in frequencies.
205     */
206    int                  pos;
207    int                  pos_bresenham_error;
208 
209    int                  loop_start;
210    int                  loop_end;
211 
212    int                  step;
213    int                  step_denom;
214                         /* The numerator and denominator of the step are
215                          * stored separately. The actual step is obtained by
216                          * dividing step by step_denom */
217 
218    float                *matrix;
219                         /* Used to convert from this format to the attached
220                          * mixers, if any.  Otherwise is NULL.
221                          * The gain is premultiplied in.
222                          */
223 
224    bool                 is_mixer;
225    stream_reader_t      spl_read;
226                         /* Reads sample data into the provided buffer, using
227                          * the specified format, converting as necessary.
228                          */
229 
230    ALLEGRO_MUTEX        *mutex;
231                         /* Points to the parent object's mutex.  It is NULL if
232                          * the sample is not directly or indirectly attached
233                          * to a voice.
234                          */
235 
236    sample_parent_t      parent;
237                         /* The object that this sample is attached to, if any.
238                          */
239    _AL_LIST_ITEM        *dtor_item;
240 };
241 
242 void _al_kcm_destroy_sample(ALLEGRO_SAMPLE_INSTANCE *sample, bool unregister);
243 void _al_kcm_stream_set_mutex(ALLEGRO_SAMPLE_INSTANCE *stream, ALLEGRO_MUTEX *mutex);
244 void _al_kcm_detach_from_parent(ALLEGRO_SAMPLE_INSTANCE *spl);
245 
246 
247 typedef size_t (*stream_callback_t)(ALLEGRO_AUDIO_STREAM *, void *, size_t);
248 typedef void (*unload_feeder_t)(ALLEGRO_AUDIO_STREAM *);
249 typedef bool (*rewind_feeder_t)(ALLEGRO_AUDIO_STREAM *);
250 typedef bool (*seek_feeder_t)(ALLEGRO_AUDIO_STREAM *, double);
251 typedef double (*get_feeder_position_t)(ALLEGRO_AUDIO_STREAM *);
252 typedef double (*get_feeder_length_t)(ALLEGRO_AUDIO_STREAM *);
253 typedef bool (*set_feeder_loop_t)(ALLEGRO_AUDIO_STREAM *, double, double);
254 
255 struct ALLEGRO_AUDIO_STREAM {
256    ALLEGRO_SAMPLE_INSTANCE spl;
257                         /* ALLEGRO_AUDIO_STREAM is derived from
258                          * ALLEGRO_SAMPLE_INSTANCE.
259                          */
260 
261    unsigned int         buf_count;
262                         /* The stream buffer is divided into a number of
263                          * fragments; this is the number of fragments.
264                          */
265 
266    void                 *main_buffer;
267                         /* Pointer to a single buffer big enough to hold all
268                          * the fragments. Each fragment has additional samples
269                          * at the start for linear/cubic interpolation.
270                          */
271 
272    void                 **pending_bufs;
273    void                 **used_bufs;
274                         /* Arrays of offsets into the main_buffer.
275                          * The arrays are each 'buf_count' long.
276                          *
277                          * 'pending_bufs' holds pointers to fragments supplied
278                          * by the user which are yet to be handed off to the
279                          * audio driver.
280                          *
281                          * 'used_bufs' holds pointers to fragments which
282                          * have been sent to the audio driver and so are
283                          * ready to receive new data.
284                          */
285 
286    volatile bool         is_draining;
287                          /* Set to true if sample data is not going to be passed
288                           * to the stream any more. The stream must change its
289                           * playing state to false after all buffers have been
290                           * played.
291                           */
292 
293    uint64_t              consumed_fragments;
294                          /* Number of complete fragment buffers consumed since
295                           * the stream was started.
296                           */
297 
298    ALLEGRO_THREAD        *feed_thread;
299    ALLEGRO_MUTEX         *feed_thread_started_mutex;
300    ALLEGRO_COND          *feed_thread_started_cond;
301    bool                  feed_thread_started;
302    volatile bool         quit_feed_thread;
303    unload_feeder_t       unload_feeder;
304    rewind_feeder_t       rewind_feeder;
305    seek_feeder_t         seek_feeder;
306    get_feeder_position_t get_feeder_position;
307    get_feeder_length_t   get_feeder_length;
308    set_feeder_loop_t     set_feeder_loop;
309    stream_callback_t     feeder;
310                          /* If ALLEGRO_AUDIO_STREAM has been created by
311                           * al_load_audio_stream(), the stream will be fed
312                           * by a thread using the 'feeder' callback. Such
313                           * streams don't need to be fed by the user.
314                           */
315 
316    _AL_LIST_ITEM        *dtor_item;
317 
318    void                  *extra;
319                          /* Extra data for use by the flac/vorbis addons. */
320 };
321 
322 bool _al_kcm_refill_stream(ALLEGRO_AUDIO_STREAM *stream);
323 
324 
325 typedef void (*postprocess_callback_t)(void *buf, unsigned int samples,
326    void *userdata);
327 
328 /* ALLEGRO_MIXER is derived from ALLEGRO_SAMPLE_INSTANCE. Certain internal functions and
329  * pointers may take either object type, and such things are explicitly noted.
330  * This is never exposed to the user, though.  The sample object's read method
331  * will be set to a different function that will call the read method of all
332  * attached streams (which may be a sample, or another mixer).
333  */
334 struct ALLEGRO_MIXER {
335    ALLEGRO_SAMPLE_INSTANCE          ss;
336                            /* ALLEGRO_MIXER is derived from ALLEGRO_SAMPLE_INSTANCE. */
337 
338    ALLEGRO_MIXER_QUALITY   quality;
339 
340    postprocess_callback_t  postprocess_callback;
341    void                    *pp_callback_userdata;
342 
343    _AL_VECTOR              streams;
344                            /* Vector of ALLEGRO_SAMPLE_INSTANCE*.  Holds the list of
345                             * streams being mixed together.
346                             */
347    _AL_LIST_ITEM           *dtor_item;
348 };
349 
350 extern void _al_kcm_mixer_rejig_sample_matrix(ALLEGRO_MIXER *mixer,
351    ALLEGRO_SAMPLE_INSTANCE *spl);
352 extern void _al_kcm_mixer_read(void *source, void **buf, unsigned int *samples,
353    ALLEGRO_AUDIO_DEPTH buffer_depth, size_t dest_maxc);
354 
355 
356 typedef enum {
357    ALLEGRO_NO_ERROR       = 0,
358    ALLEGRO_INVALID_PARAM  = 1,
359    ALLEGRO_INVALID_OBJECT = 2,
360    ALLEGRO_GENERIC_ERROR  = 255
361 } AL_ERROR_ENUM;
362 
363 extern void _al_set_error(int error, char* string);
364 
365 /* Supposedly internal */
366 ALLEGRO_KCM_AUDIO_FUNC(void*, _al_kcm_feed_stream, (ALLEGRO_THREAD *self, void *vstream));
367 
368 /* Helper to emit an event that the stream has got a buffer ready to be refilled. */
369 void _al_kcm_emit_stream_events(ALLEGRO_AUDIO_STREAM *stream);
370 
371 void _al_kcm_init_destructors(void);
372 void _al_kcm_shutdown_destructors(void);
373 _AL_LIST_ITEM *_al_kcm_register_destructor(char const *name, void *object,
374    void (*func)(void*));
375 void _al_kcm_unregister_destructor(_AL_LIST_ITEM *dtor_item);
376 void _al_kcm_foreach_destructor(
377       void (*callback)(void *object, void (*func)(void *), void *udata),
378       void *userdata);
379 
380 ALLEGRO_KCM_AUDIO_FUNC(void, _al_kcm_shutdown_default_mixer, (void));
381 
382 ALLEGRO_KCM_AUDIO_FUNC(ALLEGRO_CHANNEL_CONF, _al_count_to_channel_conf, (int num_channels));
383 ALLEGRO_KCM_AUDIO_FUNC(ALLEGRO_AUDIO_DEPTH, _al_word_size_to_depth_conf, (int word_size));
384 
385 ALLEGRO_KCM_AUDIO_FUNC(void, _al_emit_audio_event, (int event_type));
386 
387 #endif
388 
389 /* vim: set sts=3 sw=3 et: */
390