Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
338 lines (273 sloc) 10.9 KB
* Copyright (c) 2013 Andrew Kelley
* This file is part of libgroove, which is MIT licensed.
* See
#ifdef __cplusplus
extern "C"
#endif /* __cplusplus */
#include <stdint.h>
/************* global *************/
/* call once at the beginning of your program from the main thread
* returns 0 on success, < 0 on error
int groove_init(void);
/* call at the end of your program to clean up. after calling this
* you may no longer use this API.
void groove_finish(void);
/* enable/disable logging of errors
#define GROOVE_LOG_INFO 32
void groove_set_logging(int level);
/* channel layouts
#define GROOVE_CH_FRONT_LEFT 0x00000001
#define GROOVE_CH_FRONT_RIGHT 0x00000002
#define GROOVE_CH_FRONT_CENTER 0x00000004
/* get the channel count for the channel layout
int groove_channel_layout_count(uint64_t channel_layout);
/* get the default channel layout based on the channel count
uint64_t groove_channel_layout_default(int count);
enum GrooveSampleFormat {
GROOVE_SAMPLE_FMT_U8, /* unsigned 8 bits */
GROOVE_SAMPLE_FMT_S16, /* signed 16 bits */
GROOVE_SAMPLE_FMT_S32, /* signed 32 bits */
GROOVE_SAMPLE_FMT_FLT, /* float (32 bits) */
GROOVE_SAMPLE_FMT_DBL, /* double (64 bits) */
GROOVE_SAMPLE_FMT_U8P, /* unsigned 8 bits, planar */
GROOVE_SAMPLE_FMT_S16P, /* signed 16 bits, planar */
GROOVE_SAMPLE_FMT_S32P, /* signed 32 bits, planar */
GROOVE_SAMPLE_FMT_FLTP, /* float (32 bits), planar */
GROOVE_SAMPLE_FMT_DBLP /* double (64 bits), planar */
struct GrooveAudioFormat {
int sample_rate;
uint64_t channel_layout;
enum GrooveSampleFormat sample_fmt;
int groove_sample_format_bytes_per_sample(enum GrooveSampleFormat format);
int groove_version_major(void);
int groove_version_minor(void);
int groove_version_patch(void);
const char *groove_version(void);
/************* GrooveFile *************/
struct GrooveFile {
int dirty; /* read-only */
char *filename; /* read-only */
/* flags to groove_file_metadata_*
/* If the entry already exists, append to it. Note that no
* delimiter is added, the strings are simply concatenated.
struct GrooveTag;
const char *groove_tag_key(struct GrooveTag *tag);
const char *groove_tag_value(struct GrooveTag *tag);
/* you are always responsible for calling groove_file_close on the
* returned GrooveFile.
struct GrooveFile *groove_file_open(char *filename);
void groove_file_close(struct GrooveFile *file);
struct GrooveTag *groove_file_metadata_get(struct GrooveFile *file,
const char *key, const struct GrooveTag *prev, int flags);
/* key entry to add to metadata. will be strdup'd
* value entry to add to metadata. will be strdup'd
* passing NULL causes existing entry to be deleted.
* return >= 0 on success otherwise an error code < 0
* note that this will not save the file; you must call groove_file_save
* to do that.
int groove_file_metadata_set(struct GrooveFile *file, const char *key,
const char *value, int flags);
/* a comma separated list of short names for the format
const char *groove_file_short_names(struct GrooveFile *file);
/* write changes made to metadata to disk.
* return < 0 on error
int groove_file_save(struct GrooveFile *file);
/* main audio stream duration in seconds. note that this relies on a
* combination of format headers and heuristics. It can be inaccurate.
* The most accurate way to learn the duration of a file is to use
* GrooveLoudnessDetector
double groove_file_duration(struct GrooveFile *file);
/* get the audio format of the main audio stream of a file
void groove_file_audio_format(struct GrooveFile *file,
struct GrooveAudioFormat *audio_format);
/************* GroovePlaylist *************/
struct GroovePlaylistItem {
/* all fields are read-only. modify with methods below. */
struct GroovePlaylistItem *prev;
struct GrooveFile *file;
/* a volume adjustment in float format to apply to the file when it plays.
* This is typically used for ReplayGain.
* To convert from dB to float, use exp(log(10) * 0.05 * dB_value)
double gain;
struct GroovePlaylistItem *next;
struct GroovePlaylist {
/* all fields are read-only. modify using methods below.
* doubly linked list which is the playlist
struct GroovePlaylistItem *head;
struct GroovePlaylistItem *tail;
/* in float format, defaults to 1.0
double volume;
/* a playlist manages keeping an audio buffer full
* to send the buffer to your speakers, use groove_player_create
struct GroovePlaylist *groove_playlist_create(void);
/* this will not call groove_file_close on any files
* it will remove all playlist items and sinks from the playlist
void groove_playlist_destroy(struct GroovePlaylist *playlist);
void groove_playlist_play(struct GroovePlaylist *playlist);
void groove_playlist_pause(struct GroovePlaylist *playlist);
void groove_playlist_seek(struct GroovePlaylist *playlist,
struct GroovePlaylistItem *item, double seconds);
/* once you add a file to the playlist, you must not destroy it until you first
* remove it from the playlist.
* next: the item to insert before. if NULL, you will append to the playlist.
* gain: see GroovePlaylistItem structure. use 0 for no adjustment.
* returns the newly created playlist item.
struct GroovePlaylistItem *groove_playlist_insert(
struct GroovePlaylist *playlist, struct GrooveFile *file, double gain,
struct GroovePlaylistItem *next);
/* this will not call groove_file_close on item->file !
* item is destroyed and the address it points to is no longer valid
void groove_playlist_remove(struct GroovePlaylist *playlist,
struct GroovePlaylistItem *item);
/* get the position of the decode head
* both the current playlist item and the position in seconds in the playlist
* item are given. item will be set to NULL if the playlist is empty
* you may pass NULL for item or seconds
* Note that typically you are more interested in the position of the play
* head, not the decode head. For example, if you have a GroovePlayer attached,
* groove_player_position will give you the position of the play head.
void groove_playlist_position(struct GroovePlaylist *playlist,
struct GroovePlaylistItem **item, double *seconds);
/* return 1 if the playlist is playing; 0 if it is not. */
int groove_playlist_playing(struct GroovePlaylist *playlist);
/* remove all playlist items */
void groove_playlist_clear(struct GroovePlaylist *playlist);
/* return the count of playlist items */
int groove_playlist_count(struct GroovePlaylist *playlist);
void groove_playlist_set_gain(struct GroovePlaylist *playlist,
struct GroovePlaylistItem *item, double gain);
/* value is in float format. defaults to 1.0 */
void groove_playlist_set_volume(struct GroovePlaylist *playlist, double volume);
/************ GrooveBuffer ****************/
struct GrooveBuffer {
/* all fields read-only
* for interleaved audio, data[0] is the buffer.
* for planar audio, each channel has a separate data pointer.
* for encoded audio, data[0] is the encoded buffer.
uint8_t **data;
struct GrooveAudioFormat format;
/* number of audio frames described by this buffer
* for encoded audio, this is unknown and set to 0.
int frame_count;
/* when encoding, if item is NULL, this is a format header or trailer.
* otherwise, this is encoded audio for the item specified.
* when decoding, item is never NULL.
struct GroovePlaylistItem *item;
double pos;
/* total number of bytes contained in this buffer */
int size;
void groove_buffer_ref(struct GrooveBuffer *buffer);
void groove_buffer_unref(struct GrooveBuffer *buffer);
/************** GrooveSink ****************/
/* use this to get access to a realtime raw audio buffer
* for example you could use it to draw a waveform or other visualization
* GroovePlayer uses this internally to get the audio buffer for playback
struct GrooveSink {
/* set this to the audio format you want the sink to output */
struct GrooveAudioFormat audio_format;
/* Set this flag to ignore audio_format. If you set this flag, the
* buffers you pull from this sink could have any audio format.
int disable_resample;
/* If you leave this to its default of 0, frames pulled from the sink
* will have sample count determined by efficiency.
* If you set this to a positive number, frames pulled from the sink
* will always have this number of samples.
int buffer_sample_count;
/* how big the buffer queue should be, in sample frames.
* groove_sink_create defaults this to 8192
int buffer_size;
/* set to whatever you want */
void *userdata;
/* called when the audio queue is flushed. For example, if you seek to a
* different location in the song.
void (*flush)(struct GrooveSink *);
/* called when a playlist item is deleted. Take this opportunity to remove
* all your references to the GroovePlaylistItem.
void (*purge)(struct GrooveSink *, struct GroovePlaylistItem *);
/* read-only. set when you call groove_sink_attach. cleared when you call
* groove_sink_detach
struct GroovePlaylist *playlist;
/* read-only. automatically computed from audio_format when you call
* groove_sink_attach
int bytes_per_sec;
struct GrooveSink *groove_sink_create(void);
void groove_sink_destroy(struct GrooveSink *sink);
/* before calling this, set audio_format
* returns 0 on success, < 0 on error
int groove_sink_attach(struct GrooveSink *sink, struct GroovePlaylist *playlist);
/* returns 0 on success, < 0 on error */
int groove_sink_detach(struct GrooveSink *sink);
/* returns < 0 on error, GROOVE_BUFFER_NO on aborted (block=1) or no buffer
* ready (block=0), GROOVE_BUFFER_YES on buffer returned, and GROOVE_BUFFER_END
* on end of playlist.
* buffer is always set to either a valid GrooveBuffer or NULL
int groove_sink_buffer_get(struct GrooveSink *sink,
struct GrooveBuffer **buffer, int block);
/* returns < 0 on error, 0 on no buffer ready, 1 on buffer ready
* if block is 1, block until buffer is ready
int groove_sink_buffer_peek(struct GrooveSink *sink, int block);
#ifdef __cplusplus
#endif /* __cplusplus */
#endif /* GROOVE_H_INCLUDED */