### Continue encoding to a new file with ope_encoder_continue_new_file Source: https://context7.com/xiph/libopusenc/llms.txt Demonstrates closing the current file and starting a new one while maintaining the existing encoder state for efficient batch processing. ```c #include #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; float samples[960 * 2]; float frequencies[] = {261.63f, 293.66f, 329.63f, 349.23f, 392.00f}; /* C, D, E, F, G */ const char *notes[] = {"C4", "D4", "E4", "F4", "G4"}; /* Initial comments */ comments = ope_comments_create(); ope_comments_add(comments, "TITLE", notes[0]); ope_comments_add(comments, "ALBUM", "Musical Notes"); /* Create initial encoder */ enc = ope_encoder_create_file("note_C4.opus", comments, 48000, 2, 0, &error); if (!enc) { ope_comments_destroy(comments); return 1; } /* Encode first note */ for (int frame = 0; frame < 50; frame++) { /* 1 second */ for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.5f * sinf(2.0f * M_PI * frequencies[0] * t); samples[i * 2] = samples[i * 2 + 1] = sample; } ope_encoder_write_float(enc, samples, 960); } /* Continue to new files for remaining notes */ for (int n = 1; n < 5; n++) { char filename[32]; snprintf(filename, sizeof(filename), "note_%s.opus", notes[n]); /* Create new comments for this file */ OggOpusComments *new_comments = ope_comments_create(); ope_comments_add(new_comments, "TITLE", notes[n]); ope_comments_add(new_comments, "ALBUM", "Musical Notes"); /* Continue to new file */ error = ope_encoder_continue_new_file(enc, filename, new_comments); if (error != OPE_OK) { fprintf(stderr, "Continue error for %s: %s\n", filename, ope_strerror(error)); ope_comments_destroy(new_comments); break; } /* Encode this note */ for (int frame = 0; frame < 50; frame++) { for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.5f * sinf(2.0f * M_PI * frequencies[n] * t); samples[i * 2] = samples[i * 2 + 1] = sample; } ope_encoder_write_float(enc, samples, 960); } ope_comments_destroy(new_comments); } ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); printf("Created 5 note files\n"); return 0; } ``` -------------------------------- ### Control Opus Encoder Settings Source: https://context7.com/xiph/libopusenc/llms.txt Use `ope_encoder_ctl` to set or get various encoder options, including libopus and libopusenc-specific parameters. This function allows fine-grained control over bitrate, complexity, signal type, and more. ```c #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; opus_int32 value; comments = ope_comments_create(); enc = ope_encoder_create_file("ctl_example.opus", comments, 48000, 2, 0, &error); if (!enc) { ope_comments_destroy(comments); return 1; } /* Set bitrate to 128 kbps */ error = ope_encoder_ctl(enc, OPUS_SET_BITRATE(128000)); printf("Set bitrate: %s\n", error == OPE_OK ? "OK" : ope_strerror(error)); /* Get current bitrate */ error = ope_encoder_ctl(enc, OPUS_GET_BITRATE(&value)); printf("Bitrate: %d bps\n", value); /* Set complexity (0-10, higher = better quality, more CPU) */ ope_encoder_ctl(enc, OPUS_SET_COMPLEXITY(10)); /* Enable VBR (variable bitrate) */ ope_encoder_ctl(enc, OPUS_SET_VBR(1)); /* Set signal type hint (OPUS_SIGNAL_VOICE or OPUS_SIGNAL_MUSIC) */ ope_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); /* Set frame size (OPUS_FRAMESIZE_20_MS, OPUS_FRAMESIZE_40_MS, etc.) */ ope_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS)); /* libopusenc-specific: Set decision delay (samples at 48kHz) */ ope_encoder_ctl(enc, OPE_SET_DECISION_DELAY(48000)); /* 1 second */ /* Get decision delay */ ope_encoder_ctl(enc, OPE_GET_DECISION_DELAY(&value)); printf("Decision delay: %d samples\n", value); /* Set comment padding */ ope_encoder_ctl(enc, OPE_SET_COMMENT_PADDING(1024)); /* Set header gain (in 1/256 dB units) */ ope_encoder_ctl(enc, OPE_SET_HEADER_GAIN(0)); /* Get number of streams */ ope_encoder_ctl(enc, OPE_GET_NB_STREAMS(&value)); printf("Number of streams: %d\n", value); /* Get number of coupled streams */ ope_encoder_ctl(enc, OPE_GET_NB_COUPLED_STREAMS(&value)); printf("Coupled streams: %d\n", value); /* Encode some silence and finish */ float samples[960 * 2] = {0}; ope_encoder_write_float(enc, samples, 960); ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### Encoder Control API Source: https://context7.com/xiph/libopusenc/llms.txt Sets or gets encoder options using request macros. This provides access to both libopus encoder settings and libopusenc-specific options. ```APIDOC ## ope_encoder_ctl ### Description Sets or gets encoder options using request macros. This provides access to both libopus encoder settings and libopusenc-specific options. ### Method (Not applicable, this is a C function call) ### Endpoint (Not applicable, this is a C function call) ### Parameters #### Path Parameters (None) #### Query Parameters (None) #### Request Body (None) ### Request Example (Not applicable, this is a C function call) ### Response #### Success Response (OPE_OK) - **Return Value** (int) - Returns OPE_OK on success, or an error code if setting or getting the option fails. #### Response Example (See C code example in the provided text for usage) ``` -------------------------------- ### Encode WAV to Opus with Metadata Source: https://context7.com/xiph/libopusenc/llms.txt Encodes a WAV audio file to Opus format, including title and artist metadata. Ensure the input file is a valid WAV and the output path is writable. The function handles file opening, header skipping, comment creation, encoder setup, and sample buffering. ```c #include #include #include #include #include "opusenc.h" #define SAMPLE_RATE 44100 #define CHANNELS 2 #define FRAME_SAMPLES 1024 int encode_wav_to_opus(const char *input_path, const char *output_path, const char *title, const char *artist) { FILE *fin = NULL; OggOpusEnc *enc = NULL; OggOpusComments *comments = NULL; opus_int16 *buffer = NULL; int error = 0; int ret = -1; /* Open input file */ fin = fopen(input_path, "rb"); if (!fin) { fprintf(stderr, "Cannot open input: %s\n", input_path); goto cleanup; } /* Skip WAV header (assuming 44-byte standard header) */ fseek(fin, 44, SEEK_SET); /* Create comments */ comments = ope_comments_create(); if (!comments) { fprintf(stderr, "Cannot create comments\n"); goto cleanup; } if (title) ope_comments_add(comments, "TITLE", title); if (artist) ope_comments_add(comments, "ARTIST", artist); ope_comments_add(comments, "ENCODER", ope_get_version_string()); /* Create encoder */ enc = ope_encoder_create_file(output_path, comments, SAMPLE_RATE, CHANNELS, 0, &error); if (!enc) { fprintf(stderr, "Cannot create encoder: %s\n", ope_strerror(error)); goto cleanup; } /* Configure encoder for high quality music */ ope_encoder_ctl(enc, OPUS_SET_BITRATE(192000)); /* 192 kbps */ ope_encoder_ctl(enc, OPUS_SET_COMPLEXITY(10)); /* Max quality */ ope_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); ope_encoder_ctl(enc, OPUS_SET_VBR(1)); /* Variable bitrate */ ope_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(0)); /* Unconstrained VBR */ /* Allocate sample buffer */ buffer = malloc(sizeof(opus_int16) * CHANNELS * FRAME_SAMPLES); if (!buffer) { fprintf(stderr, "Cannot allocate buffer\n"); goto cleanup; } /* Encode loop */ size_t total_samples = 0; while (!feof(fin)) { int samples_read = fread(buffer, sizeof(opus_int16) * CHANNELS, FRAME_SAMPLES, fin); if (samples_read > 0) { error = ope_encoder_write(enc, buffer, samples_read); if (error != OPE_OK) { fprintf(stderr, "Encoding error: %s\n", ope_strerror(error)); goto cleanup; } total_samples += samples_read; } } /* Finalize */ error = ope_encoder_drain(enc); if (error != OPE_OK) { fprintf(stderr, "Drain error: %s\n", ope_strerror(error)); goto cleanup; } printf("Encoded %zu samples (%.2f seconds) to %s\n", total_samples, (float)total_samples / SAMPLE_RATE, output_path); ret = 0; cleanup: if (buffer) free(buffer); if (enc) ope_encoder_destroy(enc); if (comments) ope_comments_destroy(comments); if (fin) fclose(fin); return ret; } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "Usage: %s input.wav output.opus [title] [artist]\n", argv[0]); return 1; } const char *title = argc > 3 ? argv[3] : NULL; const char *artist = argc > 4 ? argv[4] : NULL; return encode_wav_to_opus(argv[1], argv[2], title, artist); } ``` -------------------------------- ### Retrieve library version with ope_get_version_string Source: https://context7.com/xiph/libopusenc/llms.txt Retrieves the library version string, API version, and ABI version for diagnostic purposes. ```c #include #include "opusenc.h" int main(void) { /* Get and display version information */ printf("libopusenc version: %s\n", ope_get_version_string()); printf("API version: %d\n", OPE_API_VERSION); printf("ABI version: %d\n", ope_get_abi_version()); /* Typical output: * libopusenc version: libopusenc 0.2.1 * API version: 0 * ABI version: 0 */ return 0; } ``` -------------------------------- ### Create file-based encoder Source: https://context7.com/xiph/libopusenc/llms.txt Initializes an encoder that writes directly to a file. Requires input sample rate, channel count, and mapping family. ```c #include #include #include "opusenc.h" #define SAMPLES_PER_READ 960 int main(int argc, char **argv) { FILE *fin; OggOpusEnc *enc; OggOpusComments *comments; int error; opus_int16 *buffer; if (argc != 3) { fprintf(stderr, "Usage: %s input.raw output.opus\n", argv[0]); return 1; } /* Open raw PCM input (16-bit signed, stereo, 44100 Hz) */ fin = fopen(argv[1], "rb"); if (!fin) { fprintf(stderr, "Cannot open input: %s\n", argv[1]); return 1; } /* Create comments with metadata */ comments = ope_comments_create(); ope_comments_add(comments, "ARTIST", "Example Artist"); ope_comments_add(comments, "TITLE", "Example Track"); /* Create encoder: 44100 Hz input, stereo, mapping family 0 */ enc = ope_encoder_create_file(argv[2], comments, 44100, 2, 0, &error); if (!enc) { fprintf(stderr, "Cannot create encoder: %s\n", ope_strerror(error)); ope_comments_destroy(comments); fclose(fin); return 1; } /* Allocate buffer for stereo samples */ buffer = malloc(sizeof(opus_int16) * 2 * SAMPLES_PER_READ); /* Encode loop */ while (1) { int samples_read = fread(buffer, sizeof(opus_int16) * 2, SAMPLES_PER_READ, fin); if (samples_read > 0) { error = ope_encoder_write(enc, buffer, samples_read); if (error != OPE_OK) { fprintf(stderr, "Encoding error: %s\n", ope_strerror(error)); break; } } else { break; /* EOF or error */ } } /* Finalize and clean up */ ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); free(buffer); fclose(fin); printf("Encoding complete: %s\n", argv[2]); return 0; } ``` -------------------------------- ### Create Opus Comments Object Source: https://context7.com/xiph/libopusenc/llms.txt Initializes a new comments object for storing Vorbis metadata. Remember to destroy the object using `ope_comments_destroy()` when finished. ```c #include #include "opusenc.h" int main(void) { OggOpusComments *comments; /* Create a new comments object */ comments = ope_comments_create(); if (comments == NULL) { fprintf(stderr, "Failed to create comments\n"); return 1; } /* Comments object is ready to add tags */ printf("Comments object created successfully\n"); /* Clean up */ ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### Force Opus Header Flush Source: https://context7.com/xiph/libopusenc/llms.txt Use `ope_encoder_flush_header` to immediately write the Opus header. This is useful when header information is needed before any audio data is encoded. Ensure the encoder is created in pull mode to observe header pages. ```c #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; unsigned char *page; opus_int32 len; comments = ope_comments_create(); ope_comments_add(comments, "TITLE", "Header Flush Example"); /* Use pull mode to observe header pages */ enc = ope_encoder_create_pull(comments, 48000, 2, 0, &error); if (!enc) { ope_comments_destroy(comments); return 1; } /* Flush header immediately */ error = ope_encoder_flush_header(enc); if (error != OPE_OK) { fprintf(stderr, "Flush header error: %s\n", ope_strerror(error)); } /* Header pages are now available */ int page_count = 0; while (ope_encoder_get_page(enc, &page, &len, 0)) { page_count++; printf("Header page %d: %d bytes\n", page_count, len); } printf("Total header pages: %d\n", page_count); /* Now we can encode audio */ float samples[960 * 2] = {0}; /* Silence */ ope_encoder_write_float(enc, samples, 960); ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### ope_comments_create Source: https://context7.com/xiph/libopusenc/llms.txt Initializes a new OggOpusComments object for storing metadata tags. ```APIDOC ## ope_comments_create ### Description Creates a new comments object for storing Vorbis metadata tags that will be embedded in the Opus file header. The comments object must be destroyed with `ope_comments_destroy()` when no longer needed. ### Method C Function ### Response - **OggOpusComments*** - A pointer to the newly created comments object, or NULL on failure. ``` -------------------------------- ### Create Opus Encoder with Custom Callbacks Source: https://context7.com/xiph/libopusenc/llms.txt Use `ope_encoder_create_callbacks` to create an encoder that writes to custom destinations like memory buffers. Requires defining `OpusEncCallbacks` with `write` and `close` functions. ```c #include #include #include "opusenc.h" /* Custom write callback - writes to a memory buffer */ typedef struct { unsigned char *data; size_t size; size_t capacity; } MemoryBuffer; int memory_write(void *user_data, const unsigned char *ptr, opus_int32 len) { MemoryBuffer *buf = (MemoryBuffer *)user_data; /* Grow buffer if needed */ while (buf->size + len > buf->capacity) { buf->capacity *= 2; buf->data = realloc(buf->data, buf->capacity); if (!buf->data) return 1; /* Error */ } memcpy(buf->data + buf->size, ptr, len); buf->size += len; return 0; /* Success */ } int memory_close(void *user_data) { /* Don't free - let caller handle it */ return 0; } int main(void) { OggOpusEnc *enc; OggOpusComments *comments; OpusEncCallbacks callbacks = { memory_write, memory_close }; MemoryBuffer buffer = { NULL, 0, 65536 }; int error; float samples[960 * 2]; /* Stereo frame */ buffer.data = malloc(buffer.capacity); if (!buffer.data) return 1; comments = ope_comments_create(); ope_comments_add(comments, "ENCODER", "Custom Memory Encoder"); /* Create encoder with callbacks */ enc = ope_encoder_create_callbacks(&callbacks, &buffer, comments, 48000, 2, 0, &error); if (!enc) { fprintf(stderr, "Failed to create encoder: %s\n", ope_strerror(error)); free(buffer.data); ope_comments_destroy(comments); return 1; } /* Generate and encode a 1-second 440Hz sine wave */ for (int frame = 0; frame < 50; frame++) { /* 50 frames * 960 samples = 48000 samples = 1 second */ for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.5f * sinf(2.0f * 3.14159f * 440.0f * t); samples[i * 2] = sample; /* Left */ samples[i * 2 + 1] = sample; /* Right */ } ope_encoder_write_float(enc, samples, 960); } ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); printf("Encoded %zu bytes to memory\n", buffer.size); /* Write to file for verification */ FILE *fp = fopen("memory_output.opus", "wb"); if (fp) { fwrite(buffer.data, 1, buffer.size, fp); fclose(fp); } free(buffer.data); return 0; } ``` -------------------------------- ### Encode 16-bit PCM with ope_encoder_write Source: https://context7.com/xiph/libopusenc/llms.txt Encodes interleaved 16-bit signed integer PCM samples. Requires samples to be provided in an interleaved format for multi-channel audio. ```c #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; opus_int16 samples[4800 * 2]; /* 100ms of stereo at 48kHz */ comments = ope_comments_create(); enc = ope_encoder_create_file("int16_output.opus", comments, 48000, 2, 0, &error); if (!enc) { fprintf(stderr, "Error: %s\n", ope_strerror(error)); ope_comments_destroy(comments); return 1; } /* Generate 5 seconds of a 440Hz sine wave */ for (int chunk = 0; chunk < 50; chunk++) { for (int i = 0; i < 4800; i++) { int sample_index = chunk * 4800 + i; float t = sample_index / 48000.0f; /* Scale to 16-bit range [-32768, 32767] */ opus_int16 sample = (opus_int16)(16000.0f * sinf(2.0f * 3.14159f * 440.0f * t)); samples[i * 2] = sample; /* Left channel */ samples[i * 2 + 1] = sample; /* Right channel */ } error = ope_encoder_write(enc, samples, 4800); if (error != OPE_OK) { fprintf(stderr, "Write error: %s\n", ope_strerror(error)); break; } } ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### Create Opus Encoder in Pull Mode Source: https://context7.com/xiph/libopusenc/llms.txt Use `ope_encoder_create_pull` to create an encoder where encoded pages are retrieved manually using `ope_encoder_get_page`. This is useful for custom container formats or muxing. ```c #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; unsigned char *page; opus_int32 page_len; FILE *output; float samples[960 * 2]; int total_pages = 0; comments = ope_comments_create(); ope_comments_add(comments, "TITLE", "Pull Mode Example"); /* Create encoder in pull mode (no callbacks) */ enc = ope_encoder_create_pull(comments, 48000, 2, 0, &error); if (!enc) { fprintf(stderr, "Failed: %s\n", ope_strerror(error)); ope_comments_destroy(comments); return 1; } output = fopen("pull_output.opus", "wb"); if (!output) { ope_encoder_destroy(enc); ope_comments_destroy(comments); return 1; } /* Generate 2 seconds of audio */ for (int frame = 0; frame < 100; frame++) { for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.3f * sinf(2.0f * 3.14159f * 880.0f * t); samples[i * 2] = sample; samples[i * 2 + 1] = sample; } ope_encoder_write_float(enc, samples, 960); /* Pull pages as they become available */ while (ope_encoder_get_page(enc, &page, &page_len, 0)) { fwrite(page, 1, page_len, output); total_pages++; } } /* Drain encoder and get remaining pages */ ope_encoder_drain(enc); while (ope_encoder_get_page(enc, &page, &page_len, 1)) { fwrite(page, 1, page_len, output); total_pages++; } printf("Written %d Ogg pages\n", total_pages); fclose(output); ope_encoder_destroy(enc); ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### ope_encoder_create_file Source: https://context7.com/xiph/libopusenc/llms.txt Creates an Opus encoder that writes directly to a specified file. This function simplifies the encoding process for creating Opus audio files. ```APIDOC ## ope_encoder_create_file ### Description Creates an encoder that writes directly to a file. This is the simplest way to encode an Opus file. The rate parameter specifies the input sample rate (will be resampled to 48kHz internally), channels is 1-255, and family is the channel mapping (0 for mono/stereo, 1 for surround). ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```c // Example usage within a C program #include "opusenc.h" FILE *fin; OggOpusEnc *enc; OggOpusComments *comments; int error; fin = fopen("input.raw", "rb"); comments = ope_comments_create(); // ... populate comments ... enc = ope_encoder_create_file("output.opus", comments, 44100, 2, 0, &error); if (!enc) { // Handle encoder creation failure } // ... encode audio data using ope_encoder_write ... ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); fclose(fin); ``` ### Response #### Success Response Returns a pointer to an `OggOpusEnc` object on success. #### Error Response Returns `NULL` if the encoder cannot be created, and sets the `error` parameter to an appropriate error code (e.g., `OPE_EINV RATE`, `OPE_EINV CHANNELS`, `OPE_EINV FAMILY`, `OPE_EFAILED`). #### Response Example ``` // Returns a pointer to an OggOpusEnc object or NULL. ``` ``` -------------------------------- ### Add picture from memory to comments Source: https://context7.com/xiph/libopusenc/llms.txt Embeds album art from a memory buffer into an OggOpusComments object. Requires the image data to be loaded into memory beforehand. ```c #include #include #include "opusenc.h" int main(void) { OggOpusComments *comments; FILE *fp; char *image_data; size_t image_size; int error; comments = ope_comments_create(); if (!comments) return 1; /* Load image into memory */ fp = fopen("cover.png", "rb"); if (fp) { fseek(fp, 0, SEEK_END); image_size = ftell(fp); fseek(fp, 0, SEEK_SET); image_data = malloc(image_size); if (image_data) { fread(image_data, 1, image_size, fp); /* Add picture from memory buffer */ error = ope_comments_add_picture_from_memory( comments, image_data, image_size, 3, /* picture_type: front cover */ "Front Cover" /* description */ ); if (error != OPE_OK) { fprintf(stderr, "Failed to add picture: %s\n", ope_strerror(error)); } free(image_data); } fclose(fp); } ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### ope_encoder_write Source: https://context7.com/xiph/libopusenc/llms.txt Encodes 16-bit signed integer PCM samples. Samples should be interleaved for multi-channel audio (L, R, L, R, ...). The function handles any number of samples per call. ```APIDOC ## ope_encoder_write ### Description Encodes 16-bit signed integer PCM samples. Samples should be interleaved for multi-channel audio (L, R, L, R, ...). The function handles any number of samples per call. ### Method (Implicitly part of the C API, not a direct HTTP method) ### Endpoint (Not applicable, this is a C library function) ### Parameters #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable, this is a C library function) ### Request Example (See C code example in the source text) ### Response #### Success Response (OPE_OK) Indicates successful encoding. #### Response Example (See C code example in the source text for error checking) ### Errors - OPE_OK: Success - Other error codes indicate failure. ``` -------------------------------- ### Encode floating-point PCM with ope_encoder_write_float Source: https://context7.com/xiph/libopusenc/llms.txt Encodes floating-point PCM samples in the range [-1.0, 1.0]. Useful for integration with audio processing libraries that natively use float samples. ```c #include #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; float samples[960 * 2]; comments = ope_comments_create(); ope_comments_add(comments, "TITLE", "Float PCM Example"); enc = ope_encoder_create_file("float_output.opus", comments, 48000, 2, 0, &error); if (!enc) { fprintf(stderr, "Error: %s\n", ope_strerror(error)); ope_comments_destroy(comments); return 1; } /* Generate a more complex stereo waveform */ for (int frame = 0; frame < 200; frame++) { for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; /* Left channel: 440Hz fundamental + 880Hz harmonic */ float left = 0.4f * sinf(2.0f * M_PI * 440.0f * t) + 0.2f * sinf(2.0f * M_PI * 880.0f * t); /* Right channel: 440Hz + slight detune for stereo width */ float right = 0.4f * sinf(2.0f * M_PI * 442.0f * t) + 0.2f * sinf(2.0f * M_PI * 884.0f * t); /* Apply fade in/out */ float envelope = 1.0f; if (t < 0.1f) envelope = t / 0.1f; else if (t > 3.9f) envelope = (4.0f - t) / 0.1f; samples[i * 2] = left * envelope; samples[i * 2 + 1] = right * envelope; } error = ope_encoder_write_float(enc, samples, 960); if (error != OPE_OK) { fprintf(stderr, "Write error: %s\n", ope_strerror(error)); break; } } ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments); printf("Encoded 4 seconds of stereo audio\n"); return 0; } ``` -------------------------------- ### Convert error codes to strings with ope_strerror Source: https://context7.com/xiph/libopusenc/llms.txt Provides a human-readable description for libopusenc error codes, useful for logging and debugging. ```c #include #include "opusenc.h" void print_error_codes(void) { int codes[] = { OPE_OK, OPE_BAD_ARG, OPE_INTERNAL_ERROR, OPE_UNIMPLEMENTED, OPE_ALLOC_FAIL, OPE_CANNOT_OPEN, OPE_TOO_LATE, OPE_INVALID_PICTURE, OPE_INVALID_ICON, OPE_WRITE_FAIL, OPE_CLOSE_FAIL }; const char *names[] = { "OPE_OK", "OPE_BAD_ARG", "OPE_INTERNAL_ERROR", "OPE_UNIMPLEMENTED", "OPE_ALLOC_FAIL", "OPE_CANNOT_OPEN", "OPE_TOO_LATE", "OPE_INVALID_PICTURE", "OPE_INVALID_ICON", "OPE_WRITE_FAIL", "OPE_CLOSE_FAIL" }; printf("libopusenc Error Codes:\n"); printf("%-25s %6s %s\n", "Name", "Value", "Description"); printf("%-25s %6s %s\n", "----", "-----", "-----------"); for (int i = 0; i < sizeof(codes)/sizeof(codes[0]); i++) { printf("%-25s %6d %s\n", names[i], codes[i], ope_strerror(codes[i])); } } int main(void) { print_error_codes(); /* Example: error handling with ope_strerror */ OggOpusComments *comments = ope_comments_create(); int error; /* Try to open a file in a non-existent directory */ OggOpusEnc *enc = ope_encoder_create_file( "/nonexistent/path/output.opus", comments, 48000, 2, 0, &error ); if (!enc) { fprintf(stderr, "Failed to create encoder: %s (error %d)\n", ope_strerror(error), error); } ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### ope_encoder_flush_header Source: https://context7.com/xiph/libopusenc/llms.txt Forces the Opus header to be written immediately rather than waiting for audio data. This is useful when header information is needed before encoding begins. ```APIDOC ## ope_encoder_flush_header ### Description Forces the Opus header to be written immediately rather than waiting for audio data. Useful when you need header information before encoding begins. ### Method (Not applicable, this is a C function call) ### Endpoint (Not applicable, this is a C function call) ### Parameters #### Path Parameters (None) #### Query Parameters (None) #### Request Body (None) ### Request Example (Not applicable, this is a C function call) ### Response #### Success Response (OPE_OK) - **Return Value** (int) - Returns OPE_OK on success, or an error code if flushing fails. #### Response Example (See C code example in the provided text for usage) ``` -------------------------------- ### Create Chained Opus Streams with Different Tracks Source: https://context7.com/xiph/libopusenc/llms.txt Use `ope_encoder_chain_current` to add new logical streams to an Opus file. Each chained stream can have its own metadata, such as title and track number. Ensure proper error handling for chaining operations. ```c #include #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments1, *comments2, *comments3; int error; float samples[960 * 2]; /* Create comments for first track */ comments1 = ope_comments_create(); ope_comments_add(comments1, "TITLE", "Track 1 - Introduction"); ope_comments_add(comments1, "TRACKNUMBER", "1"); enc = ope_encoder_create_file("chained.opus", comments1, 48000, 2, 0, &error); if (!enc) { fprintf(stderr, "Error: %s\n", ope_strerror(error)); ope_comments_destroy(comments1); return 1; } /* Encode first track (2 seconds at 440Hz) */ for (int frame = 0; frame < 100; frame++) { for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.4f * sinf(2.0f * M_PI * 440.0f * t); samples[i * 2] = samples[i * 2 + 1] = sample; } ope_encoder_write_float(enc, samples, 960); } /* Chain to second track */ comments2 = ope_comments_create(); ope_comments_add(comments2, "TITLE", "Track 2 - Development"); ope_comments_add(comments2, "TRACKNUMBER", "2"); error = ope_encoder_chain_current(enc, comments2); if (error != OPE_OK) { fprintf(stderr, "Chain error: %s\n", ope_strerror(error)); } /* Encode second track (2 seconds at 880Hz) */ for (int frame = 0; frame < 100; frame++) { for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.4f * sinf(2.0f * M_PI * 880.0f * t); samples[i * 2] = samples[i * 2 + 1] = sample; } ope_encoder_write_float(enc, samples, 960); } /* Chain to third track */ comments3 = ope_comments_create(); ope_comments_add(comments3, "TITLE", "Track 3 - Conclusion"); ope_comments_add(comments3, "TRACKNUMBER", "3"); ope_encoder_chain_current(enc, comments3); /* Encode third track (2 seconds at 660Hz) */ for (int frame = 0; frame < 100; frame++) { for (int i = 0; i < 960; i++) { float t = (frame * 960 + i) / 48000.0f; float sample = 0.4f * sinf(2.0f * M_PI * 660.0f * t); samples[i * 2] = samples[i * 2 + 1] = sample; } ope_encoder_write_float(enc, samples, 960); } ope_encoder_drain(enc); ope_encoder_destroy(enc); ope_comments_destroy(comments1); ope_comments_destroy(comments2); ope_comments_destroy(comments3); printf("Created chained stream with 3 tracks\n"); return 0; } ``` -------------------------------- ### Finalize stream with ope_encoder_drain Source: https://context7.com/xiph/libopusenc/llms.txt Flushes remaining audio and finalizes the Ogg stream. Must be called before destroying the encoder to ensure data integrity. ```c #include #include "opusenc.h" int main(void) { OggOpusEnc *enc; OggOpusComments *comments; int error; float samples[480]; /* Mono samples */ comments = ope_comments_create(); enc = ope_encoder_create_file("drained.opus", comments, 48000, 1, 0, &error); if (!enc) { ope_comments_destroy(comments); return 1; } /* Write some audio */ for (int i = 0; i < 480; i++) { samples[i] = 0.5f * sinf(2.0f * 3.14159f * 440.0f * i / 48000.0f); } ope_encoder_write_float(enc, samples, 480); /* IMPORTANT: Always drain before destroy to finalize the file */ error = ope_encoder_drain(enc); if (error != OPE_OK) { fprintf(stderr, "Drain error: %s\n", ope_strerror(error)); } /* After drain, the stream is finalized - calling drain again returns OPE_TOO_LATE */ error = ope_encoder_drain(enc); if (error == OPE_TOO_LATE) { printf("Stream already drained (expected)\n"); } ope_encoder_destroy(enc); ope_comments_destroy(comments); return 0; } ``` -------------------------------- ### ope_comments_add_string Source: https://context7.com/xiph/libopusenc/llms.txt Adds a metadata tag to the comments object using a combined tag=value string. ```APIDOC ## ope_comments_add_string ### Description Adds a metadata tag using a single "tag=value" format string. This is useful when tags are already in the combined format. ### Parameters - **comments** (OggOpusComments*) - Required - The comments object to modify. - **tag_and_value** (const char*) - Required - The string in "tag=value" format. ### Response - **int** - Returns OPE_OK on success, or an error code on failure. ``` -------------------------------- ### ope_comments_copy Source: https://context7.com/xiph/libopusenc/llms.txt Creates a deep copy of an existing OggOpusComments object. This is beneficial when you need to encode multiple files with similar metadata, allowing modifications to the copy without affecting the original. ```APIDOC ## ope_comments_copy ### Description Creates a deep copy of an existing comments object. Useful when encoding multiple files with similar metadata. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```c // Example usage within a C program #include "opusenc.h" OggOpusComments *comments, *comments_copy; comments = ope_comments_create(); // ... populate original comments ... comments_copy = ope_comments_copy(comments); if (!comments_copy) { // Handle copy failure } // ... add track-specific metadata to comments_copy ... ope_comments_destroy(comments); ope_comments_destroy(comments_copy); ``` ### Response #### Success Response Returns a pointer to a newly allocated `OggOpusComments` object that is a deep copy of the input `comments`. #### Error Response Returns `NULL` if memory allocation fails. #### Response Example ``` // Returns a pointer to an OggOpusComments object or NULL. ``` ``` -------------------------------- ### ope_encoder_write_float Source: https://context7.com/xiph/libopusenc/llms.txt Encodes floating-point PCM samples in the range [-1.0, 1.0]. This is often more convenient when working with audio processing libraries that use float samples. ```APIDOC ## ope_encoder_write_float ### Description Encodes floating-point PCM samples in the range [-1.0, 1.0]. This is often more convenient when working with audio processing libraries that use float samples. ### Method (Implicitly part of the C API, not a direct HTTP method) ### Endpoint (Not applicable, this is a C library function) ### Parameters #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable, this is a C library function) ### Request Example (See C code example in the source text) ### Response #### Success Response (OPE_OK) Indicates successful encoding. #### Response Example (See C code example in the source text for error checking) ### Errors - OPE_OK: Success - Other error codes indicate failure. ``` -------------------------------- ### ope_comments_add_picture Source: https://context7.com/xiph/libopusenc/llms.txt Embeds an image file into the comments object as metadata. ```APIDOC ## ope_comments_add_picture ### Description Embeds album art or other images from a file into the Opus stream. Picture types follow the FLAC/Vorbis specification. ### Parameters - **comments** (OggOpusComments*) - Required - The comments object to modify. - **filename** (const char*) - Required - Path to the image file. - **picture_type** (int) - Required - The type of picture (-1 for default/front cover, 0 for other, 3 for front cover, 4 for back cover, etc.). - **description** (const char*) - Optional - A description for the image. ### Response - **int** - Returns OPE_OK on success, or an error code on failure. ``` -------------------------------- ### ope_encoder_drain Source: https://context7.com/xiph/libopusenc/llms.txt Finalizes the encoding by flushing all remaining audio and completing the Ogg stream. This must be called before destroying the encoder to ensure all audio is written. ```APIDOC ## ope_encoder_drain ### Description Finalizes the encoding by flushing all remaining audio and completing the Ogg stream. This must be called before destroying the encoder to ensure all audio is written. ### Method (Implicitly part of the C API, not a direct HTTP method) ### Endpoint (Not applicable, this is a C library function) ### Parameters #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable, this is a C library function) ### Request Example (See C code example in the source text) ### Response #### Success Response (OPE_OK) Indicates successful draining of the stream. #### Response Example (See C code example in the source text for error checking) ### Errors - OPE_OK: Success - OPE_TOO_LATE: The stream has already been drained. - Other error codes indicate failure. ```