### Example: Get Server Info from Opus Stream Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Demonstrates how to initialize and use OpusServerInfo to retrieve metadata like stream name and bitrate. Remember to clear the structure after use. ```c OpusServerInfo server_info; opus_server_info_init(&server_info); OpusFileCallbacks cb; void *stream = op_url_stream_create(&cb, "http://stream.example.com:8000/opus", OP_GET_SERVER_INFO(&server_info), NULL); if (stream) { printf("Stream name: %s\n", server_info.name ? server_info.name : "unknown"); printf("Bitrate: %d kbps\n", server_info.bitrate_kbps); // ... opus_server_info_clear(&server_info); } ``` -------------------------------- ### Full Opusfile Initialization and Decoding Example Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md A comprehensive example demonstrating the full initialization process for Opusfile, including opening a file, configuring gain and dithering, checking stream parameters, retrieving metadata, and decoding audio. Includes necessary cleanup. ```c #include #include int main() { int error; // Open stream OggOpusFile *of = op_open_file("audio.opus", &error); if (!of) { fprintf(stderr, "Failed to open\n"); return 1; } // Configure output op_set_gain_offset(of, OP_HEADER_GAIN, 0); // Header gain op_set_dither_enabled(of, 1); // Enable dithering // Check parameters int channels = op_channel_count(of, -1); const OpusHead *head = op_head(of, -1); printf("Channels: %d\n", channels); printf("Input rate: %u Hz\n", head->input_sample_rate); printf("Seekable: %s\n", op_seekable(of) ? "yes" : "no"); // Get metadata const OpusTags *tags = op_tags(of, -1); const char *title = opus_tags_query(tags, "TITLE", 0); if (title) printf("Title: %s\n", title); // Configure gain based on tags int track_gain; if (opus_tags_get_track_gain(tags, &track_gain) == 0) { printf("Using track gain: %.2f dB\n", track_gain / 256.0); op_set_gain_offset(of, OP_TRACK_GAIN, 0); } // Decode audio opus_int16 pcm[5760 * 2]; int samples; while ((samples = op_read(of, pcm, 5760 * 2, NULL)) > 0) { // Process pcm... } // Cleanup op_free(of); return 0; } ``` -------------------------------- ### Example: PCM Seek to 30 Seconds Source: https://github.com/xiph/opusfile/blob/main/_autodocs/seeking.md Demonstrates using `op_pcm_seek` to target a specific time in seconds by converting it to a PCM sample offset. This method ensures precise playback start. ```c // Seek to exactly 30 seconds into the stream ogg_int64_t target_sample = 48000 * 30; int error = op_pcm_seek(of, target_sample); if (error == 0) { printf("Seeking to 30 seconds\n"); } else { fprintf(stderr, "Seek failed: %d\n", error); } ``` -------------------------------- ### Packet Analysis Example Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md An example demonstrating how to use a custom decode callback to analyze packet data. It counts packets and total samples, then defers actual decoding to the library. ```c typedef struct { int packet_count; int total_samples; } AnalysisCtx; static int analyze_packet(void *ctx, OpusMSDecoder *decoder, void *pcm, const ogg_packet *op, int nsamples, int nchannels, int format, int li) { AnalysisCtx *a = (AnalysisCtx *)ctx; a->packet_count++; a->total_samples += nsamples; return OP_DEC_USE_DEFAULT; // Use library decoding } // Usage AnalysisCtx analysis = {0}; op_set_decode_callback(of, analyze_packet, &analysis); // Read audio... printf("Packets decoded: %d\n", analysis.packet_count); printf("Total samples: %d\n", analysis.total_samples); ``` -------------------------------- ### Progress Tracking and Seeking Example Source: https://github.com/xiph/opusfile/blob/main/_autodocs/seeking.md Shows how to retrieve the current playback position and total duration in PCM samples, convert them to seconds, and then seek forward by a specified duration. ```c // Check current position and total duration ogg_int64_t current = op_pcm_tell(of); ogg_int64_t total = op_pcm_total(of, -1); if (total > 0) { double current_time = current / 48000.0; double total_time = total / 48000.0; printf("Position: %.2f / %.2f seconds\n", current_time, total_time); } // Seek forward 10 seconds ogg_int64_t new_position = current + (48000 * 10); op_pcm_seek(of, new_position); ``` -------------------------------- ### Chained Stream Seeking Example Source: https://github.com/xiph/opusfile/blob/main/_autodocs/seeking.md Demonstrates seeking within chained Ogg Opus files. It shows how to get the total duration, seek to the middle, and check the current link and channel count, which may change after crossing link boundaries. ```c // Assume a chained stream with 3 links printf("Total links: %d\n", op_link_count(of)); // Seek to middle of stream ogg_int64_t mid = op_pcm_total(of, -1) / 2; op_pcm_seek(of, mid); // May have crossed to a different link printf("Current link: %d\n", op_current_link(of)); // Channel count can change printf("Channels in this link: %d\n", op_channel_count(of, -1)); ``` -------------------------------- ### Example Usage of OpusFileCallbacks Source: https://github.com/xiph/opusfile/blob/main/_autodocs/types.md Demonstrates how to initialize and use the OpusFileCallbacks structure to open an OggOpusFile with custom stream handling. Requires implementing the callback functions. ```c OpusFileCallbacks cb = { .read = my_read_func, .seek = my_seek_func, .tell = my_tell_func, .close = my_close_func }; int error; OggOpusFile *of = op_open_callbacks(stream, &cb, NULL, 0, &error); ``` -------------------------------- ### Create URL Stream with HTTP Proxy Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Example of creating an opus URL stream using HTTP proxy configuration macros. ```c op_url_stream_create(&cb, "http://example.com/audio.opus", OP_HTTP_PROXY_HOST("proxy.company.com"), OP_HTTP_PROXY_PORT(8080), OP_HTTP_PROXY_USER("username"), OP_HTTP_PROXY_PASS("password"), NULL); ``` -------------------------------- ### Simple Opusfile Playback Source: https://github.com/xiph/opusfile/blob/main/_autodocs/index.md Basic example demonstrating how to open an Opus file, read audio data in a loop, and play it. Ensure `play_audio` is implemented to handle PCM data and channel counts. ```c int error; OggOpusFile *of = op_open_file("audio.opus", &error); opus_int16 pcm[5760 * 2]; int samples; while ((samples = op_read(of, pcm, 5760 * 2, NULL)) > 0) { play_audio(pcm, samples, op_channel_count(of, -1)); } op_free(of); ``` -------------------------------- ### Interactive Seeking Player Example Source: https://github.com/xiph/opusfile/blob/main/_autodocs/seeking.md Demonstrates how to open an Opus file, check for seekability, calculate duration, perform a seek operation to a specific PCM target, and then decode audio. Requires `opusfile.h` and `stdio.h`. ```c #include #include int main() { int error; OggOpusFile *of = op_open_file("audio.opus", &error); if (!of) return 1; if (!op_seekable(of)) { fprintf(stderr, "Stream not seekable\n"); op_free(of); return 1; } ogg_int64_t total = op_pcm_total(of, -1); double duration = total / 48000.0; printf("Stream duration: %.2f seconds\n", duration); // Seek to 1/4 through the file ogg_int64_t target = total / 4; error = op_pcm_seek(of, target); if (error == 0) { double target_time = target / 48000.0; printf("Sought to %.2f seconds\n", target_time); } // Decode and process audio... opus_int16 pcm[5760 * 2]; int samples; while ((samples = op_read(of, pcm, 5760 * 2, NULL)) > 0) { // Process samples... } op_free(of); return 0; } ``` -------------------------------- ### Build openssl for MinGW Source: https://github.com/xiph/opusfile/blob/main/mingw/README.md Configure and build the OpenSSL library for MinGW. Ensure to specify the correct cross-compilation prefix and installation path. ```bash CROSS_COMPILE="i686-w64-mingw32-" ./Configure mingw no-asm no-shared --prefix=$PWD/mingw && make depend && make -j8 && make install ``` -------------------------------- ### Example: Raw Seek to 1/4 File Position Source: https://github.com/xiph/opusfile/blob/main/_autodocs/seeking.md Demonstrates how to use `op_raw_seek` to move to a specific byte offset, calculated as a fraction of the total file size. Ensure the stream is seekable before attempting. ```c int error; OggOpusFile *of = op_open_file("audio.opus", &error); if (op_seekable(of)) { // Seek to 1/4 through the file opus_int64 total = op_raw_total(of, -1); if (total > 0) { error = op_raw_seek(of, total / 4); if (error == 0) { printf("Seek successful\n"); } } } ``` -------------------------------- ### Getting Stream Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/README.md Shows how to retrieve basic stream information such as channel count and duration using `op_head()` and `op_pcm_total()`. ```APIDOC ## Getting Stream Information ### Description Retrieves essential information about the Opus stream, including header details and total duration in PCM samples. ### Method `op_head(OggOpusFile *of, int link)` `op_pcm_total(OggOpusFile *of, int link)` ### Parameters #### Path Parameters - **of** (OggOpusFile *) - Required - The OggOpusFile handle. - **link** (int) - Required - The link index (usually -1 for the first link). ### Request Example ```c const OpusHead *head = op_head(of, -1); printf("Channels: %d\n", head->channel_count); printf("Duration: %.2f seconds\n", op_pcm_total(of, -1) / 48000.0); ``` ``` -------------------------------- ### Configure Opusfile for cross-compilation Source: https://github.com/xiph/opusfile/blob/main/mingw/README.md Configure Opusfile for building dynamic libraries with a specified host and installation directory. The PKG_CONFIG_PATH should point to the build directory's pkgconfig folder. ```bash ./configure --host=i686-w64-mingw32 --prefix=/path/to/builddir/mingw \ PKG_CONFIG_PATH=/path/to/builddir/mingw/lib/pkgconfig ``` -------------------------------- ### Accessing Opus Head Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/types.md Example demonstrating how to access and print information from an OpusHead structure obtained from an OggOpusFile handle. It shows how to retrieve version, channel count, input sample rate, and output gain. ```c const OpusHead *head = op_head(of, 0); printf("Version: %d\n", head->version); printf("Channels: %d\n", head->channel_count); printf("Input rate: %u Hz (output always 48 kHz)\n", head->input_sample_rate); printf("Gain: %d/256 dB\n", head->output_gain); ``` -------------------------------- ### Get Instantaneous Bitrate Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the instantaneous bitrate since the last call or seek. Works for unseekable streams and is reset by calling again. Spikes may occur after a seek. ```c opus_int32 op_bitrate_instant(OggOpusFile *_of); ``` ```c // After reading some samples... opus_int32 inst_bitrate = op_bitrate_instant(of); if (inst_bitrate > 0) { printf("Instantaneous bitrate: %u kbps\n", inst_bitrate / 1000); } ``` -------------------------------- ### Custom Opusfile Callbacks Implementation Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Provides a full example of implementing custom read, seek, tell, and close callbacks for opusfile. This allows opusfile to read from custom data sources. ```c #include #include // Custom stream state typedef struct { FILE *file; char name[256]; } MyStream; // Read callback static int my_read(void *stream, unsigned char *ptr, int nbytes) { MyStream *s = (MyStream *)stream; int n = fread(ptr, 1, nbytes, s->file); return (n > 0 || feof(s->file)) ? n : -1; } // Seek callback static int my_seek(void *stream, opus_int64 offset, int whence) { MyStream *s = (MyStream *)stream; if (fseek(s->file, (long)offset, whence) < 0) { return -1; } return 0; } // Tell callback static opus_int64 my_tell(void *stream) { MyStream *s = (MyStream *)stream; return ftell(s->file); } // Close callback (optional) static int my_close(void *stream) { MyStream *s = (MyStream *)stream; if (fclose(s->file) < 0) { return EOF; } free(s); return 0; } // Usage int main() { MyStream *stream = malloc(sizeof(MyStream)); stream->file = fopen("audio.opus", "rb"); snprintf(stream->name, sizeof(stream->name), "audio.opus"); OpusFileCallbacks cb = { .read = my_read, .seek = my_seek, .tell = my_tell, .close = my_close }; int error; OggOpusFile *of = op_open_callbacks(stream, &cb, NULL, 0, &error); if (!of) { fprintf(stderr, "Failed to open: %d\n", error); return 1; } // Decode... op_free(of); // Calls my_close return 0; } ``` -------------------------------- ### op_bitrate_instant Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the instantaneous bitrate since the last call or seek. This function is useful for monitoring real-time bitrate fluctuations, especially for unseekable streams. ```APIDOC ## op_bitrate_instant ### Description Gets the instantaneous bitrate since last call or seek. ### Method ```c opus_int32 op_bitrate_instant(OggOpusFile *_of); ``` ### Parameters #### Path Parameters - `_of` (OggOpusFile *) - Required - Decoder handle ### Return: - Instantaneous bitrate in bits per second on success - `OP_FALSE` — No data decoded since last call/seek - `OP_EINVAL` — Stream only partially open ### Notes: - Computed from bits and playable samples since last call, seek, or playback start - Spikes after seek due to pre-skip and pre-roll - Works for unseekable streams (unlike `op_bitrate()`) - Reset by calling again ### Example: ```c // After reading some samples... opus_int32 inst_bitrate = op_bitrate_instant(of); if (inst_bitrate > 0) { printf("Instantaneous bitrate: %u kbps\n", inst_bitrate / 1000); } ``` ``` -------------------------------- ### Accessing Opus Tags and Vendor Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/types.md Example showing how to retrieve OpusTags from an OggOpusFile handle and print the vendor string and comment count. It also demonstrates querying for a specific tag, 'TITLE', and printing its value if found. ```c const OpusTags *tags = op_tags(of, -1); if (tags) { printf("Vendor: %s\n", tags->vendor); printf("Comments: %d\n", tags->comments); const char *title = opus_tags_query(tags, "TITLE", 0); if (title) printf("Title: %s\n", title); } ``` -------------------------------- ### Handle OP_EBADPACKET Decode Error Source: https://github.com/xiph/opusfile/blob/main/_autodocs/errors.md Illustrates how to detect and handle OP_EBADPACKET, which occurs when a packet fails to decode due to corruption or transmission errors. The example shows how to log the error and continue reading. ```c int samples = op_read(of, pcm, buf_size, NULL); if (samples == OP_EBADPACKET) { fprintf(stderr, "Bad packet (corruption or transmission error)\n"); // Continue or stop depending on application requirements } ``` -------------------------------- ### Get Raw Stream Byte Position Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the current byte position within the Ogg Opus stream. This function returns the raw byte offset being read. It returns OP_EINVAL if the stream is only partially open. ```c opus_int64 op_raw_tell(const OggOpusFile *_of); ``` -------------------------------- ### opus_tags_query_count Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Gets the number of instances of a specific tag within an OpusTags structure. This is useful for iterating through all values associated with a tag. ```APIDOC ## opus_tags_query_count ### Description Gets the number of instances of a given tag within the `OpusTags` structure. This is useful for determining how many values are associated with a particular tag. ### Method int ### Parameters #### Path Parameters - `_tags` (const OpusTags *) - Required - `OpusTags` structure to query. - `_tag` (const char *) - Required - The tag name to count instances of. ### Return - The number of instances of this tag (greater than or equal to 0). ### Notes - Tag comparison is case-insensitive. - Returns 0 if the tag is not found. ``` -------------------------------- ### Create release archive Source: https://github.com/xiph/opusfile/blob/main/mingw/README.md Package the contents of the release directory into a zip archive. This command is run from the parent directory of the release folder. ```bash zip -r opusfile-${version}-win32.zip opusfile-${version}-win32/* ``` -------------------------------- ### op_pcm_total Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the total PCM sample count of the stream or a specific link. This function is useful for determining the duration of audio content. ```APIDOC ## op_pcm_total ### Description Gets the total PCM sample count of the stream or a link. ### Method ```c ogg_int64_t op_pcm_total(const OggOpusFile *_of, int _li); ``` ### Parameters #### Path Parameters - `_of` (const OggOpusFile *) - Required - Decoder handle - `_li` (int) - Required - Link index; negative = entire stream ### Return: - Total PCM samples (at 48 kHz) on success - Negative error code on failure ### Errors: - `OP_EINVAL` — Stream not seekable or out of range ### Notes: - All Opus audio decodes to 48 kHz - Divide by 48000 to get duration in seconds - Only available for seekable streams - Includes pre-skip and post-trimming (samples that won't be heard) ### Example: ```c ogg_int64_t pcm_samples = op_pcm_total(of, -1); if (pcm_samples > 0) { double duration = pcm_samples / 48000.0; printf("Duration: %.2f seconds\n", duration); } ``` ``` -------------------------------- ### Seeking by Time Conversion to PCM Samples Source: https://github.com/xiph/opusfile/blob/main/_autodocs/seeking.md Illustrates how to convert a desired time in seconds into a PCM sample offset for use with `op_pcm_seek`. Two methods are shown: direct conversion and conversion with rounding. ```c double seconds = 45.5; ogg_int64_t sample_offset = (ogg_int64_t)(seconds * 48000); int error = op_pcm_seek(of, sample_offset); ``` ```c double seconds = 45.5; ogg_int64_t sample_offset = (ogg_int64_t)(0.5 + seconds * 48000); int error = op_pcm_seek(of, sample_offset); ``` -------------------------------- ### Configure HTTP Proxy with Authentication Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md Use these macros to configure an HTTP proxy with authentication when opening a URL. Ensure both user and password are provided for authentication to work. ```c #define OP_HTTP_PROXY_HOST(_host) // const char * #define OP_HTTP_PROXY_PORT(_port) // opus_int32, default 8080 #define OP_HTTP_PROXY_USER(_user) // const char * #define OP_HTTP_PROXY_PASS(_pass) // const char * ``` ```c OggOpusFile *of = op_open_url("https://example.com/audio.opus", &error, OP_HTTP_PROXY_HOST("proxy.corp.com"), OP_HTTP_PROXY_PORT(8080), OP_HTTP_PROXY_USER("username"), OP_HTTP_PROXY_PASS("password"), NULL); ``` -------------------------------- ### Display Opusfile Metadata Source: https://github.com/xiph/opusfile/blob/main/_autodocs/index.md Example of how to retrieve and display metadata tags from an Opus file. It queries for 'TITLE' and 'ARTIST' tags using `opus_tags_query`. ```c const OpusTags *tags = op_tags(of, -1); printf("Title: %s\n", opus_tags_query(tags, "TITLE", 0)); printf("Artist: %s\n", opus_tags_query(tags, "ARTIST", 0)); ``` -------------------------------- ### op_fopen for Standard File I/O Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Opens a file using standard I/O and fills in the OpusFileCallbacks structure. It handles 64-bit seeking and avoids cross-module FILE* issues on Windows. ```c void *op_fopen(OpusFileCallbacks *_cb, const char *_path, const char *_mode); ``` ```c OpusFileCallbacks cb; void *stream = op_fopen(&cb, "audio.opus", "rb"); if (stream) { int error; OggOpusFile *of = op_open_callbacks(stream, &cb, NULL, 0, &error); // Use of... op_free(of); // Also closes stream via cb.close() } ``` -------------------------------- ### Get Track Gain from Opus Tags Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Extracts the R128_TRACK_GAIN value from Opus tags, used for per-track volume normalization. The format and range are the same as R128_ALBUM_GAIN. ```c int opus_tags_get_track_gain(const OpusTags *_tags, int *_gain_q8); ``` -------------------------------- ### Opening a File Source: https://github.com/xiph/opusfile/blob/main/_autodocs/README.md Demonstrates how to open an Opus audio file using `op_open_file()` and includes basic error handling. ```APIDOC ## Opening a File ### Description Opens an Opus audio file for decoding. Includes error checking. ### Method `op_open_file(const char *path, int *error)` ### Parameters #### Path Parameters - **path** (const char *) - Required - The path to the Opus file. - **error** (int *) - Required - A pointer to an integer to store any error code. ### Request Example ```c #include int error; OggOpusFile *of = op_open_file("audio.opus", &error); if (!of) { fprintf(stderr, "Failed to open: %d\n", error); return; } ``` ``` -------------------------------- ### Initialize OpusServerInfo Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md Initialize an OpusServerInfo structure to receive server metadata. It is crucial to clear the structure after you are finished with it. ```c OpusServerInfo server; opus_server_info_init(&server); // ... use server ... opus_server_info_clear(&server); ``` -------------------------------- ### Get Average Bitrate Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Computes the average bitrate of the specified link or the entire stream. Includes Ogg muxing overhead and is only available for seekable streams. ```c opus_int32 op_bitrate(const OggOpusFile *_of, int _li); ``` ```c opus_int32 bitrate = op_bitrate(of, -1); if (bitrate > 0) { printf("Bitrate: %u kbps\n", bitrate / 1000); } ``` -------------------------------- ### op_channel_count Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the number of audio channels for a specific link in the Opus stream. This is useful for determining playback requirements, such as whether stereo downmixing is needed. ```APIDOC ## op_channel_count ### Description Gets the number of channels in a link. ### Method C Function ### Parameters #### Path Parameters - `_of` (const OggOpusFile *) - Required - Decoder handle - `_li` (int) - Required - Link index; negative = current link ### Return - Channel count (1–255) - Last link's count if `_li` exceeds link count - Current link's count if unseekable ### Notes - Convenience function; equivalent to accessing `OpusHead.channel_count` - Can change between links in chained streams - Use `op_read_stereo()` / `op_read_float_stereo()` to force stereo output ### Example ```c int channels = op_channel_count(of, -1); // Current link printf("Channels: %d\n", channels); if (channels != 2 && channels != 1) { // Use stereo downmixing for multichannel op_read_stereo(of, stereo_buffer, buffer_size); } ``` ``` -------------------------------- ### opus_server_info_init Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Initializes an OpusServerInfo structure for handling server information, particularly for URL streams. Requires linking against libopusurl. ```APIDOC ## opus_server_info_init ### Description Initializes an `OpusServerInfo` structure for handling server information, particularly for URL streams. Requires linking against `libopusurl`. ### Method void ### Parameters: - `_info` (OpusServerInfo *) - Yes - Pointer to the `OpusServerInfo` structure to initialize. ``` -------------------------------- ### op_fdopen for Existing File Descriptors Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Opens an existing file descriptor with callbacks, allowing integration with existing file handles. ```c void *op_fdopen(OpusFileCallbacks *_cb, int _fd, const char *_mode); ``` -------------------------------- ### opus_granule_sample Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Converts a granule position to a sample offset relative to the stream start after pre-skip. Returns -1 if the granule position is less than the pre-skip value. ```APIDOC ## opus_granule_sample ### Description Converts a granule position to a sample offset. ### Method C Function ### Parameters #### Path Parameters - `_head` (const OpusHead *) - Required - OpusHead from stream - `_gp` (ogg_int64_t) - Required - Granule position ### Return - Sample offset (relative to stream start after pre-skip) - `-1` if granule position is less than `pre_skip` ### Notes - Handles overflow wrapping in signed 64-bit values - Granule positions before `pre_skip` represent unplayable audio - Formula: `sample_offset = granule_position - pre_skip` ``` -------------------------------- ### Compiling with Opusfile and URL Support Source: https://github.com/xiph/opusfile/blob/main/_autodocs/README.md Compiles an application with opusfile, including URL support. This requires linking against libopusurl, libopusfile, libopus, libogg, and libcurl. ```bash # With URL support (requires libopusurl) gcc myapp.c -lopusurl -lopusfile -lopus -logg -lcurl ``` -------------------------------- ### Get Total PCM Samples Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieves the total number of PCM samples for the entire stream or a specific link. Useful for calculating audio duration. Requires a seekable stream. ```c ogg_int64_t op_pcm_total(const OggOpusFile *_of, int _li); ``` ```c ogg_int64_t pcm_samples = op_pcm_total(of, -1); if (pcm_samples > 0) { double duration = pcm_samples / 48000.0; printf("Duration: %.2f seconds\n", duration); } ``` -------------------------------- ### op_fopen Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Opens a file using standard I/O and fills in the OpusFileCallbacks structure. ```APIDOC ## op_fopen ### Description Opens a file and fills in callbacks for standard I/O. ### Function Signature ```c void *op_fopen(OpusFileCallbacks *_cb, const char *_path, const char *_mode); ``` ### Parameters - **_cb** (`OpusFileCallbacks *`) - Callback structure to fill (Required) - **_path** (`const char *`) - File path (UTF-8 on Windows) (Required) - **_mode** (`const char *`) - Open mode ("rb" recommended) (Required) ### Return Value - Stream handle for use with callbacks on success - `NULL` on error ### Notes - Avoids cross-module FILE* issues on Windows - Automatically handles 64-bit seeking - Callbacks filled in for read/seek/tell/close ### Example ```c OpusFileCallbacks cb; void *stream = op_fopen(&cb, "audio.opus", "rb"); if (stream) { int error; OggOpusFile *of = op_open_callbacks(stream, &cb, NULL, 0, &error); // Use of... op_free(of); // Also closes stream via cb.close() } ``` ``` -------------------------------- ### Get Serial Number of an Opus Stream Link Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Obtain the unique serial number for a specific link (or the current link if unseekable) within an Opus stream using `op_serialno`. ```c opus_uint32 op_serialno(const OggOpusFile *_of, int _li); ``` -------------------------------- ### Configure HTTP Proxy Settings Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Defines macros for setting HTTP proxy host, port, username, and password when creating a URL stream. ```c #define OP_HTTP_PROXY_HOST(_host) #define OP_HTTP_PROXY_PORT(_port) #define OP_HTTP_PROXY_USER(_user) #define OP_HTTP_PROXY_PASS(_pass) ``` -------------------------------- ### Get Opus File Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/README.md Retrieves header information and calculates the total duration of the Opus stream in seconds. Assumes a sample rate of 48000 Hz for duration calculation. ```c const OpusHead *head = op_head(of, -1); printf("Channels: %d\n", head->channel_count); printf("Duration: %.2f seconds\n", op_pcm_total(of, -1) / 48000.0); ``` -------------------------------- ### op_current_link Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the index of the current link in a chained Opusfile stream. This is useful for tracking progress in multi-link streams, especially for unseekable streams where the index increments as new links are encountered. ```APIDOC ## op_current_link ### Description Gets the index of the current link in a chained stream. ### Method C Function ### Parameters #### Path Parameters - `_of` (const OggOpusFile *) - Required - Decoder handle ### Return: - Current link index (0-based) on success - Negative error code on failure ### Errors: - `OP_EINVAL` — Stream only partially open ### Notes: - For seekable streams: index is 0 to `op_link_count() - 1` - For unseekable streams: starts at 0, increments when new link encountered - Reflects most recent read or seek result ``` -------------------------------- ### Get Channel Count for an Opus Stream Link Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Determine the number of audio channels in a specific link of an Opus stream using `op_channel_count`. This function is equivalent to accessing `OpusHead.channel_count` directly. ```c int op_channel_count(const OggOpusFile *_of, int _li); ``` ```c int channels = op_channel_count(of, -1); // Current link printf("Channels: %d\n", channels); if (channels != 2 && channels != 1) { // Use stereo downmixing for multichannel op_read_stereo(of, stereo_buffer, buffer_size); } ``` -------------------------------- ### Initialize Opus Server Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Initializes an OpusServerInfo structure for managing server information, particularly for URL streams. Requires linking against libopusurl. ```c void opus_server_info_init(OpusServerInfo *_info); ``` -------------------------------- ### Build opusfile for MinGW Source: https://github.com/xiph/opusfile/blob/main/mingw/README.md Compile the Opusfile library using a MinGW C compiler and specifying the package configuration path. ```bash CC=i686-w64-mingw32-gcc PKG_CONFIG_PATH=$PWD/lib/pkgconfig RANLIB=i686-w64-mingw32-ranlib make -f ../unix/Makefile ``` -------------------------------- ### Get Number of Links in Opus Stream Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieve the total number of logical streams (links) within a seekable Opus file using `op_link_count`. For unseekable streams, it returns 1. ```c int op_link_count(const OggOpusFile *_of); ``` ```c int links = op_link_count(of); printf("Stream contains %d link(s)\n", links); ``` -------------------------------- ### Get Opus Header Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieves the ID header information for a specific link or the current link. The returned pointer must not be modified and remains valid until the next stream operation or free. ```c const OpusHead *op_head(const OggOpusFile *_of, int _li); ``` ```c const OpusHead *head = op_head(of, -1); printf("Version: %d\n", head->version); printf("Channels: %d\n", head->channel_count); printf("Input sample rate: %u Hz\n", head->input_sample_rate); printf("Stream count: %d (coupled: %d)\n", head->stream_count, head->coupled_count); ``` -------------------------------- ### Check Stream Parameters Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md Demonstrates how to retrieve and interpret stream parameters like channel count and original sample rate after opening an Opus file. This information is read-only after stream initialization. ```c OggOpusFile *of = op_open_file("audio.opus", NULL); const OpusHead *head = op_head(of, 0); int channels = head->channel_count; uint32_t orig_rate = head->input_sample_rate; printf("Channels: %d\n", channels); printf("Original sample rate: %u Hz\n", orig_rate); printf("Output sample rate: 48000 Hz\n"); if (channels > 2) { printf("Multichannel detected; using stereo downmixing\n"); // Use op_read_stereo or op_read_float_stereo } else { printf("Mono or stereo; can use standard read\n"); // Use op_read or op_read_float } ``` -------------------------------- ### Compiling with Opusfile Core Library Source: https://github.com/xiph/opusfile/blob/main/_autodocs/README.md Compiles an application using the core opusfile library. This command links against libopusfile, libopus, and libogg. ```bash # Core library gcc myapp.c -lopusfile -lopus -logg ``` -------------------------------- ### Initialize OpusTags Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md Initialize an OpusTags structure before using it to store or query metadata tags. Remember to clear the structure when done. ```c OpusTags tags; opus_tags_init(&tags); // ... use tags ... opus_tags_clear(&tags); ``` -------------------------------- ### Handling Errors During File Opening Source: https://github.com/xiph/opusfile/blob/main/_autodocs/errors.md Demonstrates how to handle specific errors returned by op_open_file, such as OP_ENOTFORMAT or OP_EFAULT. ```c // Opening int error; OggOpusFile *of = op_open_file("audio.opus", &error); if (!of) { switch (error) { case OP_ENOTFORMAT: fprintf(stderr, "Not an Opus file\n"); break; case OP_EFAULT: fprintf(stderr, "Memory error or file not found\n"); break; default: fprintf(stderr, "Error: %d\n", error); } return; } ``` -------------------------------- ### Retrieve Server Metadata Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md Use the OP_GET_SERVER_INFO macro to retrieve metadata from streaming servers like Icecast or Shoutcast. Initialize the OpusServerInfo structure before use and clear it afterwards. ```c #define OP_GET_SERVER_INFO(_info) // OpusServerInfo * ``` ```c OpusServerInfo server; opus_server_info_init(&server); int error; OggOpusFile *of = op_open_url("http://stream.example.com:8000/live", &error, OP_GET_SERVER_INFO(&server), NULL); if (of) { if (server.name) printf("Stream: %s\n", server.name); if (server.genre) printf("Genre: %s\n", server.genre); if (server.bitrate_kbps > 0) { printf("Bitrate: %d kbps\n", server.bitrate_kbps); } // Use stream... op_free(of); opus_server_info_clear(&server); } ``` -------------------------------- ### Configure SSL Certificate Verification Source: https://github.com/xiph/opusfile/blob/main/_autodocs/configuration.md Shows how to configure SSL certificate verification when opening URLs. The OP_SSL_SKIP_CERTIFICATE_CHECK option can be used to disable verification for testing, but is not recommended for production. ```c // Verify certificate (default, more secure) OggOpusFile *of = op_open_url("https://example.com/audio.opus", &error, OP_SSL_SKIP_CERTIFICATE_CHECK(0), NULL); // Skip verification (testing only) OggOpusFile *of = op_open_url("https://example.com/audio.opus", &error, OP_SSL_SKIP_CERTIFICATE_CHECK(1), NULL); ``` -------------------------------- ### op_pcm_tell Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Gets the PCM (Pulse Code Modulation) sample offset of the next sample to be read from the Opusfile stream. This is useful for tracking playback progress, especially when calculating percentages relative to the total number of samples. ```APIDOC ## op_pcm_tell ### Description Gets the PCM offset of the next sample to be read. ### Method C Function ### Parameters #### Path Parameters - `_of` (const OggOpusFile *) - Required - Decoder handle ### Return: - PCM sample offset (at 48 kHz) - `OP_EINVAL` if only partially open ### Notes: - May not increment by expected amount or return monotonic values if stream improperly timestamped - Useful for progress tracking ### Example: ```c ogg_int64_t current_sample = op_pcm_tell(of); ogg_int64_t total_samples = op_pcm_total(of, -1); if (total_samples > 0) { double progress = 100.0 * current_sample / total_samples; printf("Progress: %.1f%%\n", progress); } ``` ``` -------------------------------- ### Handling Errors During Seeking Source: https://github.com/xiph/opusfile/blob/main/_autodocs/errors.md Shows how to check for and handle seeking errors like OP_ENOSEEK or OP_EINVAL when using op_pcm_seek. ```c // Seeking int error = op_pcm_seek(of, target); if (error < 0) { if (error == OP_ENOSEEK) { fprintf(stderr, "Cannot seek\n"); } else if (error == OP_EINVAL) { fprintf(stderr, "Invalid seek target\n"); } return; } ``` -------------------------------- ### Generate SHA256 checksums and GPG signature Source: https://github.com/xiph/opusfile/blob/main/mingw/README.md Create a SHA256 checksum file for all files in the release directory and then sign the checksum file using GPG. These are typically done in the release directory. ```bash sha256sum * > SHA256SUMS.txt gpg --detach-sign --armor SHA256SUMS.txt ``` -------------------------------- ### Get Compressed Size of Opus Stream Link Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieve the compressed size in bytes of a specific link or the entire stream using `op_raw_total`. This function requires a seekable stream and returns the size including Ogg muxing overhead. ```c opus_int64 op_raw_total(const OggOpusFile *_of, int _li); ``` ```c opus_int64 total_bytes = op_raw_total(of, -1); if (total_bytes > 0) { printf("Stream size: %lld bytes\n", total_bytes); } ``` -------------------------------- ### Get Album Gain from Opus Tags Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Extracts the R128_ALBUM_GAIN value from Opus tags. This function searches for the first valid signed 16-bit decimal R128_ALBUM_GAIN tag. The gain value is in 1/256ths of a dB and is applied in addition to the header gain. ```c int opus_tags_get_album_gain(const OpusTags *_tags, int *_gain_q8); ``` -------------------------------- ### op_fdopen Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Opens an existing file descriptor and associates it with the OpusFileCallbacks structure. ```APIDOC ## op_fdopen ### Description Opens an existing file descriptor with callbacks. ### Function Signature ```c void *op_fdopen(OpusFileCallbacks *_cb, int _fd, const char *_mode); ``` ### Parameters - **_cb** (`OpusFileCallbacks *`) - Callback structure to fill (Required) - **_fd** (`int`) - File descriptor (from `open()`, `fileno()`, etc.) (Required) - **_mode** (`const char *`) - File mode string (Required) ### Return Value - Stream handle on success - `NULL` on error ``` -------------------------------- ### Get Opus Tags from Stream Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieves the comment header (metadata tags) for a specified link within an OggOpusFile. Can be used on partially opened streams, returning tags from the first link in such cases. The returned pointer is internal and should not be freed or modified. ```c const OpusTags *op_tags(const OggOpusFile *_of, int _li); ``` ```c const OpusTags *tags = op_tags(of, -1); if (tags) { const char *artist = opus_tags_query(tags, "ARTIST", 0); const char *title = opus_tags_query(tags, "TITLE", 0); if (artist) printf("Artist: %s\n", artist); if (title) printf("Title: %s\n", title); } ``` -------------------------------- ### Include Opusfile Header Source: https://github.com/xiph/opusfile/blob/main/_autodocs/index.md Demonstrates the necessary include directive for using the opusfile library. All function declarations and type definitions are available in this single header file. ```c #include ``` -------------------------------- ### Get PCM Sample Offset Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieves the PCM sample offset for the next sample to be read from the stream, calculated at 48 kHz. This is useful for progress tracking. Note that values may not be monotonic if the stream has improper timestamps. Returns OP_EINVAL if the stream is only partially open. ```c ogg_int64_t op_pcm_tell(const OggOpusFile *_of); ``` ```c ogg_int64_t current_sample = op_pcm_tell(of); ogg_int64_t total_samples = op_pcm_total(of, -1); if (total_samples > 0) { double progress = 100.0 * current_sample / total_samples; printf("Progress: %.1f%%\n", progress); } ``` -------------------------------- ### Get Current Link Index Source: https://github.com/xiph/opusfile/blob/main/_autodocs/stream-information.md Retrieves the index of the current link in a chained Ogg Opus stream. For seekable streams, this is the 0-based index of the link. For unseekable streams, it increments as new links are encountered. Returns a negative error code if the stream is only partially open. ```c int op_current_link(const OggOpusFile *_of); ``` -------------------------------- ### Basic Opus File Decoding Source: https://github.com/xiph/opusfile/blob/main/_autodocs/overview.md Opens an Opus file, reads audio data in chunks, and processes it. Ensure the file exists and is a valid Ogg Opus stream. The buffer size should accommodate the expected audio data. ```c #include int error; OggOpusFile *of = op_open_file("audio.opus", &error); if (!of) { // Handle error return; } int samples_per_channel; opus_int16 pcm[5760 * 2]; // 120ms at 48kHz, stereo int link_index; while ((samples_per_channel = op_read(of, pcm, 5760 * 2, &link_index)) > 0) { // Process samples // samples_per_channel = number of samples per channel // link_index = which link in a chained stream } op_free(of); ``` -------------------------------- ### Retrieve Server Information Source: https://github.com/xiph/opusfile/blob/main/_autodocs/callbacks-urls.md Defines a macro to retrieve server information, such as HTTP headers, for Shoutcast/Icecast streams. The server_info structure may contain invalid values. ```c #define OP_GET_SERVER_INFO(_info) ``` -------------------------------- ### opus_picture_tag_init Source: https://github.com/xiph/opusfile/blob/main/_autodocs/headers-metadata.md Initializes an OpusPictureTag structure, preparing it for use. ```APIDOC ## opus_picture_tag_init ### Description Initializes an `OpusPictureTag` structure, preparing it for use. ### Method void ### Parameters: - `_pic` (OpusPictureTag *) - Yes - Pointer to the `OpusPictureTag` structure to initialize. ```