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