1 /*
2  * Copyright (c) 2013 Andrew Kelley
3  *
4  * This file is part of libgroove, which is MIT licensed.
5  * See http://opensource.org/licenses/MIT
6  */
7 
8 #ifndef GROOVE_H_INCLUDED
9 #define GROOVE_H_INCLUDED
10 
11 #include <stdint.h>
12 
13 #ifdef __cplusplus
14 extern "C"
15 {
16 #endif /* __cplusplus */
17 
18 /************* global *************/
19 
20 /* call once at the beginning of your program from the main thread
21  * returns 0 on success, < 0 on error
22  */
23 int groove_init(void);
24 /* call at the end of your program to clean up. after calling this
25  * you may no longer use this API.
26  */
27 void groove_finish(void);
28 
29 /* enable/disable logging of errors
30  */
31 #define GROOVE_LOG_QUIET    -8
32 #define GROOVE_LOG_ERROR    16
33 #define GROOVE_LOG_WARNING  24
34 #define GROOVE_LOG_INFO     32
35 void groove_set_logging(int level);
36 
37 
38 /* channel layouts
39  */
40 #define GROOVE_CH_FRONT_LEFT               0x00000001
41 #define GROOVE_CH_FRONT_RIGHT              0x00000002
42 #define GROOVE_CH_FRONT_CENTER             0x00000004
43 #define GROOVE_CH_LOW_FREQUENCY            0x00000008
44 #define GROOVE_CH_BACK_LEFT                0x00000010
45 #define GROOVE_CH_BACK_RIGHT               0x00000020
46 #define GROOVE_CH_FRONT_LEFT_OF_CENTER     0x00000040
47 #define GROOVE_CH_FRONT_RIGHT_OF_CENTER    0x00000080
48 #define GROOVE_CH_BACK_CENTER              0x00000100
49 #define GROOVE_CH_SIDE_LEFT                0x00000200
50 #define GROOVE_CH_SIDE_RIGHT               0x00000400
51 #define GROOVE_CH_TOP_CENTER               0x00000800
52 #define GROOVE_CH_TOP_FRONT_LEFT           0x00001000
53 #define GROOVE_CH_TOP_FRONT_CENTER         0x00002000
54 #define GROOVE_CH_TOP_FRONT_RIGHT          0x00004000
55 #define GROOVE_CH_TOP_BACK_LEFT            0x00008000
56 #define GROOVE_CH_TOP_BACK_CENTER          0x00010000
57 #define GROOVE_CH_TOP_BACK_RIGHT           0x00020000
58 #define GROOVE_CH_STEREO_LEFT              0x20000000
59 #define GROOVE_CH_STEREO_RIGHT             0x40000000
60 #define GROOVE_CH_WIDE_LEFT                0x0000000080000000ULL
61 #define GROOVE_CH_WIDE_RIGHT               0x0000000100000000ULL
62 
63 #define GROOVE_CH_LAYOUT_MONO              (GROOVE_CH_FRONT_CENTER)
64 #define GROOVE_CH_LAYOUT_STEREO            (GROOVE_CH_FRONT_LEFT|GROOVE_CH_FRONT_RIGHT)
65 #define GROOVE_CH_LAYOUT_2POINT1           (GROOVE_CH_LAYOUT_STEREO|GROOVE_CH_LOW_FREQUENCY)
66 #define GROOVE_CH_LAYOUT_2_1               (GROOVE_CH_LAYOUT_STEREO|GROOVE_CH_BACK_CENTER)
67 #define GROOVE_CH_LAYOUT_SURROUND          (GROOVE_CH_LAYOUT_STEREO|GROOVE_CH_FRONT_CENTER)
68 #define GROOVE_CH_LAYOUT_3POINT1           (GROOVE_CH_LAYOUT_SURROUND|GROOVE_CH_LOW_FREQUENCY)
69 #define GROOVE_CH_LAYOUT_4POINT0           (GROOVE_CH_LAYOUT_SURROUND|GROOVE_CH_BACK_CENTER)
70 #define GROOVE_CH_LAYOUT_4POINT1           (GROOVE_CH_LAYOUT_4POINT0|GROOVE_CH_LOW_FREQUENCY)
71 #define GROOVE_CH_LAYOUT_2_2               (GROOVE_CH_LAYOUT_STEREO|GROOVE_CH_SIDE_LEFT|GROOVE_CH_SIDE_RIGHT)
72 #define GROOVE_CH_LAYOUT_QUAD              (GROOVE_CH_LAYOUT_STEREO|GROOVE_CH_BACK_LEFT|GROOVE_CH_BACK_RIGHT)
73 #define GROOVE_CH_LAYOUT_5POINT0           (GROOVE_CH_LAYOUT_SURROUND|GROOVE_CH_SIDE_LEFT|GROOVE_CH_SIDE_RIGHT)
74 #define GROOVE_CH_LAYOUT_5POINT1           (GROOVE_CH_LAYOUT_5POINT0|GROOVE_CH_LOW_FREQUENCY)
75 #define GROOVE_CH_LAYOUT_5POINT0_BACK      (GROOVE_CH_LAYOUT_SURROUND|GROOVE_CH_BACK_LEFT|GROOVE_CH_BACK_RIGHT)
76 #define GROOVE_CH_LAYOUT_5POINT1_BACK      (GROOVE_CH_LAYOUT_5POINT0_BACK|GROOVE_CH_LOW_FREQUENCY)
77 #define GROOVE_CH_LAYOUT_6POINT0           (GROOVE_CH_LAYOUT_5POINT0|GROOVE_CH_BACK_CENTER)
78 #define GROOVE_CH_LAYOUT_6POINT0_FRONT     (GROOVE_CH_LAYOUT_2_2|GROOVE_CH_FRONT_LEFT_OF_CENTER|GROOVE_CH_FRONT_RIGHT_OF_CENTER)
79 #define GROOVE_CH_LAYOUT_HEXAGONAL         (GROOVE_CH_LAYOUT_5POINT0_BACK|GROOVE_CH_BACK_CENTER)
80 #define GROOVE_CH_LAYOUT_6POINT1           (GROOVE_CH_LAYOUT_5POINT1|GROOVE_CH_BACK_CENTER)
81 #define GROOVE_CH_LAYOUT_6POINT1_BACK      (GROOVE_CH_LAYOUT_5POINT1_BACK|GROOVE_CH_BACK_CENTER)
82 #define GROOVE_CH_LAYOUT_6POINT1_FRONT     (GROOVE_CH_LAYOUT_6POINT0_FRONT|GROOVE_CH_LOW_FREQUENCY)
83 #define GROOVE_CH_LAYOUT_7POINT0           (GROOVE_CH_LAYOUT_5POINT0|GROOVE_CH_BACK_LEFT|GROOVE_CH_BACK_RIGHT)
84 #define GROOVE_CH_LAYOUT_7POINT0_FRONT     (GROOVE_CH_LAYOUT_5POINT0|GROOVE_CH_FRONT_LEFT_OF_CENTER|GROOVE_CH_FRONT_RIGHT_OF_CENTER)
85 #define GROOVE_CH_LAYOUT_7POINT1           (GROOVE_CH_LAYOUT_5POINT1|GROOVE_CH_BACK_LEFT|GROOVE_CH_BACK_RIGHT)
86 #define GROOVE_CH_LAYOUT_7POINT1_WIDE      (GROOVE_CH_LAYOUT_5POINT1|GROOVE_CH_FRONT_LEFT_OF_CENTER|GROOVE_CH_FRONT_RIGHT_OF_CENTER)
87 #define GROOVE_CH_LAYOUT_7POINT1_WIDE_BACK (GROOVE_CH_LAYOUT_5POINT1_BACK|GROOVE_CH_FRONT_LEFT_OF_CENTER|GROOVE_CH_FRONT_RIGHT_OF_CENTER)
88 #define GROOVE_CH_LAYOUT_OCTAGONAL         (GROOVE_CH_LAYOUT_5POINT0|GROOVE_CH_BACK_LEFT|GROOVE_CH_BACK_CENTER|GROOVE_CH_BACK_RIGHT)
89 #define GROOVE_CH_LAYOUT_STEREO_DOWNMIX    (GROOVE_CH_STEREO_LEFT|GROOVE_CH_STEREO_RIGHT)
90 
91 /* get the channel count for the channel layout
92  */
93 int groove_channel_layout_count(uint64_t channel_layout);
94 
95 /* get the default channel layout based on the channel count
96  */
97 uint64_t groove_channel_layout_default(int count);
98 
99 enum GrooveSampleFormat {
100     GROOVE_SAMPLE_FMT_NONE = -1,
101     GROOVE_SAMPLE_FMT_U8,          /* unsigned 8 bits */
102     GROOVE_SAMPLE_FMT_S16,         /* signed 16 bits */
103     GROOVE_SAMPLE_FMT_S32,         /* signed 32 bits */
104     GROOVE_SAMPLE_FMT_FLT,         /* float (32 bits) */
105     GROOVE_SAMPLE_FMT_DBL,         /* double (64 bits) */
106 
107     GROOVE_SAMPLE_FMT_U8P,         /* unsigned 8 bits, planar */
108     GROOVE_SAMPLE_FMT_S16P,        /* signed 16 bits, planar */
109     GROOVE_SAMPLE_FMT_S32P,        /* signed 32 bits, planar */
110     GROOVE_SAMPLE_FMT_FLTP,        /* float (32 bits), planar */
111     GROOVE_SAMPLE_FMT_DBLP         /* double (64 bits), planar */
112 };
113 
114 struct GrooveAudioFormat {
115     int sample_rate;
116     uint64_t channel_layout;
117     enum GrooveSampleFormat sample_fmt;
118 };
119 
120 int groove_sample_format_bytes_per_sample(enum GrooveSampleFormat format);
121 
122 /* returns 1 if the audio formats have the same sample rate, channel layout,
123  * and sample format. returns 0 otherwise. */
124 int groove_audio_formats_equal(const struct GrooveAudioFormat *a, const struct GrooveAudioFormat *b);
125 
126 
127 int groove_version_major(void);
128 int groove_version_minor(void);
129 int groove_version_patch(void);
130 const char *groove_version(void);
131 
132 /************* GrooveFile *************/
133 struct GrooveFile {
134     int dirty; /* read-only */
135     const char *filename; /* read-only */
136 };
137 
138 /* flags to groove_file_metadata_*
139  */
140 #define GROOVE_TAG_MATCH_CASE      1
141 #define GROOVE_TAG_DONT_OVERWRITE 16
142 
143 /* If the entry already exists, append to it.  Note that no
144  * delimiter is added, the strings are simply concatenated.
145  */
146 #define GROOVE_TAG_APPEND         32
147 
148 struct GrooveTag;
149 
150 const char *groove_tag_key(struct GrooveTag *tag);
151 const char *groove_tag_value(struct GrooveTag *tag);
152 
153 /* you are always responsible for calling groove_file_close on the
154  * returned GrooveFile.
155  */
156 struct GrooveFile *groove_file_open(const char *filename);
157 void groove_file_close(struct GrooveFile *file);
158 
159 struct GrooveTag *groove_file_metadata_get(struct GrooveFile *file,
160         const char *key, const struct GrooveTag *prev, int flags);
161 /* key entry to add to metadata. will be strdup'd
162  * value entry to add to metadata. will be strdup'd
163  *    passing NULL causes existing entry to be deleted.
164  * return >= 0 on success otherwise an error code < 0
165  * note that this will not save the file; you must call groove_file_save
166  * to do that.
167  */
168 int groove_file_metadata_set(struct GrooveFile *file, const char *key,
169         const char *value, int flags);
170 
171 /* a comma separated list of short names for the format
172  */
173 const char *groove_file_short_names(struct GrooveFile *file);
174 
175 /* write changes made to metadata to disk.
176  * return < 0 on error
177  */
178 int groove_file_save(struct GrooveFile *file);
179 
180 /* main audio stream duration in seconds. note that this relies on a
181  * combination of format headers and heuristics. It can be inaccurate.
182  * The most accurate way to learn the duration of a file is to use
183  * GrooveLoudnessDetector
184  */
185 double groove_file_duration(struct GrooveFile *file);
186 
187 /* get the audio format of the main audio stream of a file
188  */
189 void groove_file_audio_format(struct GrooveFile *file,
190         struct GrooveAudioFormat *audio_format);
191 
192 /************* GroovePlaylist *************/
193 struct GroovePlaylistItem {
194     /* all fields are read-only. modify with methods below. */
195 
196     struct GrooveFile *file;
197 
198     /* A volume adjustment in float format to apply to the file when it plays.
199      * This is typically used for loudness compensation, for example ReplayGain.
200      * To convert from dB to float, use exp(log(10) * 0.05 * dB_value)
201      */
202     double gain;
203 
204     /* The sample peak of this playlist item is assumed to be 1.0 in float
205      * format. If you know for certain that the peak is less than 1.0, you
206      * may set this value which may allow the volume adjustment to use
207      * a pure amplifier rather than a compressor. This results in slightly
208      * better audio quality.
209      */
210     double peak;
211 
212     /* A GroovePlaylist is a doubly linked list. Use these fields to
213      * traverse the list.
214      */
215     struct GroovePlaylistItem *prev;
216     struct GroovePlaylistItem *next;
217 };
218 
219 struct GroovePlaylist {
220     /* all fields are read-only. modify using methods below.
221      * doubly linked list which is the playlist
222      */
223     struct GroovePlaylistItem *head;
224     struct GroovePlaylistItem *tail;
225 
226     /* volume adjustment in float format which applies to all playlist items
227      * and all sinks. defaults to 1.0.
228      */
229     double gain;
230 };
231 
232 /* a playlist keeps its sinks full.
233  */
234 struct GroovePlaylist *groove_playlist_create(void);
235 /* this will not call groove_file_close on any files
236  * it will remove all playlist items and sinks from the playlist
237  */
238 void groove_playlist_destroy(struct GroovePlaylist *playlist);
239 
240 
241 void groove_playlist_play(struct GroovePlaylist *playlist);
242 void groove_playlist_pause(struct GroovePlaylist *playlist);
243 
244 void groove_playlist_seek(struct GroovePlaylist *playlist,
245         struct GroovePlaylistItem *item, double seconds);
246 
247 /* once you add a file to the playlist, you must not destroy it until you first
248  * remove it from the playlist.
249  * next: the item to insert before. if NULL, you will append to the playlist.
250  * gain: see GroovePlaylistItem structure. use 1.0 for no adjustment.
251  * peak: see GroovePlaylistItem structure. use 1.0 for no adjustment.
252  * returns the newly created playlist item, or NULL if out of memory.
253  */
254 struct GroovePlaylistItem *groove_playlist_insert(
255         struct GroovePlaylist *playlist, struct GrooveFile *file,
256         double gain, double peak,
257         struct GroovePlaylistItem *next);
258 
259 /* this will not call groove_file_close on item->file !
260  * item is destroyed and the address it points to is no longer valid
261  */
262 void groove_playlist_remove(struct GroovePlaylist *playlist,
263         struct GroovePlaylistItem *item);
264 
265 /* get the position of the decode head
266  * both the current playlist item and the position in seconds in the playlist
267  * item are given. item will be set to NULL if the playlist is empty
268  * seconds will be set to -1.0 if item is NULL.
269  * you may pass NULL for item or seconds
270  * Note that typically you are more interested in the position of the play
271  * head, not the decode head. For example, if you have a GroovePlayer attached,
272  * groove_player_position will give you the position of the play head.
273  */
274 void groove_playlist_position(struct GroovePlaylist *playlist,
275         struct GroovePlaylistItem **item, double *seconds);
276 
277 /* return 1 if the playlist is playing; 0 if it is not.  */
278 int groove_playlist_playing(struct GroovePlaylist *playlist);
279 
280 
281 /* remove all playlist items */
282 void groove_playlist_clear(struct GroovePlaylist *playlist);
283 
284 /* return the count of playlist items */
285 int groove_playlist_count(struct GroovePlaylist *playlist);
286 
287 void groove_playlist_set_gain(struct GroovePlaylist *playlist, double gain);
288 
289 void groove_playlist_set_item_gain(struct GroovePlaylist *playlist,
290         struct GroovePlaylistItem *item, double gain);
291 
292 void groove_playlist_set_item_peak(struct GroovePlaylist *playlist,
293         struct GroovePlaylistItem *item, double peak);
294 
295 /* This is the default behavior. The playlist will decode audio if any sinks
296  * are not full. If any sinks do not drain fast enough the data will buffer up
297  * in the playlist.
298  */
299 #define GROOVE_EVERY_SINK_FULL 0
300 
301 /* With this behavior, the playlist will stop decoding audio when any attached
302  * sink is full, and then resume decoding audio every sink is not full.
303  */
304 #define GROOVE_ANY_SINK_FULL   1
305 
306 /* Use this to set the fill mode using the constants above */
307 void groove_playlist_set_fill_mode(struct GroovePlaylist *playlist, int mode);
308 
309 /************ GrooveBuffer ****************/
310 
311 #define GROOVE_BUFFER_NO  0
312 #define GROOVE_BUFFER_YES 1
313 #define GROOVE_BUFFER_END 2
314 
315 struct GrooveBuffer {
316     /* all fields read-only
317      * for interleaved audio, data[0] is the buffer.
318      * for planar audio, each channel has a separate data pointer.
319      * for encoded audio, data[0] is the encoded buffer.
320      */
321     uint8_t **data;
322 
323     struct GrooveAudioFormat format;
324 
325     /* number of audio frames described by this buffer
326      * for encoded audio, this is unknown and set to 0.
327      */
328     int frame_count;
329 
330     /* when encoding, if item is NULL, this is a format header or trailer.
331      * otherwise, this is encoded audio for the item specified.
332      * when decoding, item is never NULL.
333      */
334     struct GroovePlaylistItem *item;
335     double pos;
336 
337     /* total number of bytes contained in this buffer */
338     int size;
339 
340     /* presentation time stamp of the buffer */
341     uint64_t pts;
342 };
343 
344 void groove_buffer_ref(struct GrooveBuffer *buffer);
345 void groove_buffer_unref(struct GrooveBuffer *buffer);
346 
347 /************** GrooveSink ****************/
348 
349 /* use this to get access to a realtime raw audio buffer
350  * for example you could use it to draw a waveform or other visualization
351  * GroovePlayer uses this internally to get the audio buffer for playback
352  */
353 
354 struct GrooveSink {
355     /* set this to the audio format you want the sink to output */
356     struct GrooveAudioFormat audio_format;
357     /* Set this flag to ignore audio_format. If you set this flag, the
358      * buffers you pull from this sink could have any audio format.
359      */
360     int disable_resample;
361     /* If you leave this to its default of 0, frames pulled from the sink
362      * will have sample count determined by efficiency.
363      * If you set this to a positive number, frames pulled from the sink
364      * will always have this number of samples.
365      */
366     int buffer_sample_count;
367 
368     /* how big the buffer queue should be, in sample frames.
369      * groove_sink_create defaults this to 8192
370      */
371     int buffer_size;
372 
373     /* This volume adjustment only applies to this sink.
374      * It is recommended that you leave this at 1.0 and instead adjust the
375      * gain of the playlist.
376      * If you want to change this value after you have already attached the
377      * sink to the playlist, you must use groove_sink_set_gain.
378      * float format. Defaults to 1.0
379      */
380     double gain;
381 
382     /* set to whatever you want */
383     void *userdata;
384     /* called when the audio queue is flushed. For example, if you seek to a
385      * different location in the song.
386      */
387     void (*flush)(struct GrooveSink *);
388     /* called when a playlist item is deleted. Take this opportunity to remove
389      * all your references to the GroovePlaylistItem.
390      */
391     void (*purge)(struct GrooveSink *, struct GroovePlaylistItem *);
392     /* called when the playlist is paused */
393     void (*pause)(struct GrooveSink *);
394     /* called when the playlist is played */
395     void (*play)(struct GrooveSink *);
396 
397     /* read-only. set when you call groove_sink_attach. cleared when you call
398      * groove_sink_detach
399      */
400     struct GroovePlaylist *playlist;
401 
402     /* read-only. automatically computed from audio_format when you call
403      * groove_sink_attach
404      */
405     int bytes_per_sec;
406 };
407 
408 struct GrooveSink *groove_sink_create(void);
409 void groove_sink_destroy(struct GrooveSink *sink);
410 
411 /* before calling this, set audio_format
412  * returns 0 on success, < 0 on error
413  */
414 int groove_sink_attach(struct GrooveSink *sink, struct GroovePlaylist *playlist);
415 /* returns 0 on success, < 0 on error */
416 int groove_sink_detach(struct GrooveSink *sink);
417 
418 /* returns < 0 on error, GROOVE_BUFFER_NO on aborted (block=1) or no buffer
419  * ready (block=0), GROOVE_BUFFER_YES on buffer returned, and GROOVE_BUFFER_END
420  * on end of playlist.
421  * buffer is always set to either a valid GrooveBuffer or NULL
422  */
423 int groove_sink_buffer_get(struct GrooveSink *sink,
424         struct GrooveBuffer **buffer, int block);
425 
426 /* returns < 0 on error, 0 on no buffer ready, 1 on buffer ready
427  * if block is 1, block until buffer is ready
428  */
429 int groove_sink_buffer_peek(struct GrooveSink *sink, int block);
430 
431 /* See the gain property of GrooveSink. It is recommended that you leave this
432  * at 1.0 and instead adjust the gain of the playlist.
433  * returns 0 on success, < 0 on error
434  */
435 int groove_sink_set_gain(struct GrooveSink *sink, double gain);
436 
437 
438 #ifdef __cplusplus
439 }
440 #endif /* __cplusplus */
441 
442 #endif /* GROOVE_H_INCLUDED */
443