This commit is contained in:
intelligence committed 2026-08-29 23:11:50 +02:00
1 parent 32e7f32e0a
commit 523acd3349
23 files changed
+482 -98

No files matched your search

+123
View File
@@ -0,0 +1,123 @@
#include "transui_mp3.h"
#include "layer3.h"
#include <stdlib.h>
#include <string.h>
static int append_bytes(uint8_t **output, size_t *size, size_t *capacity,
const unsigned char *bytes, size_t byte_count) {
if (byte_count == 0) return TRANSUI_MP3_OK;
if (*size > SIZE_MAX - byte_count) return TRANSUI_MP3_OUT_OF_MEMORY;
const size_t required = *size + byte_count;
if (required > *capacity) {
size_t next_capacity = *capacity;
while (next_capacity < required) {
if (next_capacity > SIZE_MAX / 2) {
next_capacity = required;
break;
}
next_capacity *= 2;
}
uint8_t *resized = realloc(*output, next_capacity);
if (!resized) return TRANSUI_MP3_OUT_OF_MEMORY;
*output = resized;
*capacity = next_capacity;
}
memcpy(*output + *size, bytes, byte_count);
*size = required;
return TRANSUI_MP3_OK;
}
int transui_mp3_encode_mono_16k_32kbps(const uint8_t *pcm_le,
size_t pcm_byte_count,
uint8_t **output,
size_t *output_size) {
if (!output || !output_size) return TRANSUI_MP3_INVALID_INPUT;
*output = NULL;
*output_size = 0;
if (!pcm_le || pcm_byte_count < 2 || pcm_byte_count % 2 != 0) {
return TRANSUI_MP3_INVALID_INPUT;
}
if (pcm_byte_count / 8 > SIZE_MAX - 8192) {
return TRANSUI_MP3_OUT_OF_MEMORY;
}
shine_config_t config;
config.wave.channels = PCM_MONO;
config.wave.samplerate = 16000;
shine_set_config_mpeg_defaults(&config.mpeg);
config.mpeg.mode = MONO;
config.mpeg.bitr = 32;
shine_t encoder = shine_initialise(&config);
if (!encoder) return TRANSUI_MP3_ENCODER_ERROR;
const int samples_per_pass = shine_samples_per_pass(encoder);
if (samples_per_pass <= 0) {
shine_close(encoder);
return TRANSUI_MP3_ENCODER_ERROR;
}
int16_t *frame = calloc((size_t)samples_per_pass, sizeof(int16_t));
size_t capacity = pcm_byte_count / 8 + 8192;
uint8_t *encoded = malloc(capacity);
if (!frame || !encoded) {
free(frame);
free(encoded);
shine_close(encoder);
return TRANSUI_MP3_OUT_OF_MEMORY;
}
const size_t sample_count = pcm_byte_count / 2;
size_t sample_offset = 0;
size_t encoded_size = 0;
int result = TRANSUI_MP3_OK;
while (sample_offset < sample_count) {
const size_t remaining = sample_count - sample_offset;
const size_t frame_samples =
remaining < (size_t)samples_per_pass ? remaining
: (size_t)samples_per_pass;
memset(frame, 0, (size_t)samples_per_pass * sizeof(int16_t));
for (size_t index = 0; index < frame_samples; ++index) {
const size_t byte_offset = (sample_offset + index) * 2;
frame[index] = (int16_t)((uint16_t)pcm_le[byte_offset] |
((uint16_t)pcm_le[byte_offset + 1] << 8));
}
int written = 0;
unsigned char *bytes =
shine_encode_buffer_interleaved(encoder, frame, &written);
if (written < 0 || (!bytes && written > 0)) {
result = TRANSUI_MP3_ENCODER_ERROR;
break;
}
result = append_bytes(&encoded, &encoded_size, &capacity, bytes,
(size_t)written);
if (result != TRANSUI_MP3_OK) break;
sample_offset += frame_samples;
}
if (result == TRANSUI_MP3_OK) {
int written = 0;
unsigned char *bytes = shine_flush(encoder, &written);
if (written < 0 || (!bytes && written > 0)) {
result = TRANSUI_MP3_ENCODER_ERROR;
} else {
result = append_bytes(&encoded, &encoded_size, &capacity, bytes,
(size_t)written);
}
}
free(frame);
shine_close(encoder);
if (result != TRANSUI_MP3_OK || encoded_size == 0) {
free(encoded);
return result == TRANSUI_MP3_OK ? TRANSUI_MP3_ENCODER_ERROR : result;
}
*output = encoded;
*output_size = encoded_size;
return TRANSUI_MP3_OK;
}
void transui_mp3_free(void *memory) { free(memory); }