diff --git a/sbc/sbc.c b/sbc/sbc.c index c95862a..9669bb9 100644 --- a/sbc/sbc.c +++ b/sbc/sbc.c @@ -1230,23 +1230,24 @@ int sbc_init(sbc_t *sbc, unsigned long flags) return 0; } -int sbc_parse(sbc_t *sbc, void *data, int count) +int sbc_parse(sbc_t *sbc, void *input, int input_len) { - return sbc_decode(sbc, data, count); + return sbc_decode(sbc, input, input_len, NULL, 0, NULL); } -int sbc_decode(sbc_t *sbc, void *data, int count) +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) { struct sbc_priv *priv; char *ptr; int i, ch, framelen, samples; - if (!sbc) + if (!sbc && !input) return -EIO; priv = sbc->priv; - framelen = sbc_unpack_frame(data, &priv->frame, count); + framelen = sbc_unpack_frame(input, &priv->frame, input_len); if (!priv->init) { sbc_decoder_init(&priv->dec_state, &priv->frame); @@ -1259,24 +1260,18 @@ int sbc_decode(sbc_t *sbc, void *data, int count) sbc->bitpool = priv->frame.bitpool; } - samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); + if (!output) + return framelen; - if (!sbc->data) { - sbc->size = samples * priv->frame.channels * 2; - sbc->data = malloc(sbc->size); - } + if (written) + *written = 0; - if (sbc->size < samples * priv->frame.channels * 2) { - sbc->size = samples * priv->frame.channels * 2; - sbc->data = realloc(sbc->data, sbc->size); - } + samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame); - if (!sbc->data) { - sbc->size = 0; - return -ENOMEM; - } + ptr = output; - ptr = sbc->data; + if (output_len < samples * priv->frame.channels * 2) + samples = output_len / (priv->frame.channels * 2); for (i = 0; i < samples; i++) { for (ch = 0; ch < priv->frame.channels; ch++) { @@ -1293,22 +1288,27 @@ int sbc_decode(sbc_t *sbc, void *data, int count) } } - sbc->len = samples * priv->frame.channels * 2; + if (written) + *written = samples * priv->frame.channels * 2; return framelen; } -int sbc_encode(sbc_t *sbc, void *data, int count) +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written) { struct sbc_priv *priv; char *ptr; - int i, ch, framelen, samples; + int i, ch, framelen, samples, ret; - if (!sbc) + if (!sbc && !input) return -EIO; priv = sbc->priv; + if (written) + *written = 0; + if (!priv->init) { priv->frame.sampling_frequency = sbc->rate; priv->frame.channels = sbc->channels; @@ -1331,10 +1331,10 @@ int sbc_encode(sbc_t *sbc, void *data, int count) } /* input must be large enough to encode a complete frame */ - if (count < priv->frame.subbands * priv->frame.blocks * sbc->channels * 2) + if (input_len < priv->frame.subbands * priv->frame.blocks * sbc->channels * 2) return 0; - ptr = data; + ptr = input; for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) { for (ch = 0; ch < sbc->channels; ch++) { @@ -1351,23 +1351,19 @@ int sbc_encode(sbc_t *sbc, void *data, int count) samples = sbc_analyze_audio(&priv->enc_state, &priv->frame); - if (!sbc->data) { - sbc->size = 1024; - sbc->data = malloc(sbc->size); - } + ret = samples * sbc->channels * 2; - if (!sbc->data) { - sbc->size = 0; - return -ENOMEM; - } + if (!output || output_len < ret) + return ret; - framelen = sbc_pack_frame(sbc->data, &priv->frame, sbc->size); + framelen = sbc_pack_frame(output, &priv->frame, 1024); - sbc->len = framelen; + if (written) + *written = framelen; sbc->duration = (1000000 * priv->frame.subbands * priv->frame.blocks) / sbc->rate; - return samples * sbc->channels * 2; + return ret; } void sbc_finish(sbc_t *sbc) @@ -1375,9 +1371,6 @@ void sbc_finish(sbc_t *sbc) if (!sbc) return; - if (sbc->data) - free(sbc->data); - if (sbc->priv) free(sbc->priv); diff --git a/sbc/sbc.h b/sbc/sbc.h index 72512c0..d7a74ec 100644 --- a/sbc/sbc.h +++ b/sbc/sbc.h @@ -42,10 +42,6 @@ struct sbc_struct { int bitpool; int swap; - void *data; - int size; - int len; - unsigned long duration; void *priv; @@ -54,9 +50,11 @@ struct sbc_struct { typedef struct sbc_struct sbc_t; int sbc_init(sbc_t *sbc, unsigned long flags); -int sbc_parse(sbc_t *sbc, void *data, int count); -int sbc_decode(sbc_t *sbc, void *data, int count); -int sbc_encode(sbc_t *sbc, void *data, int count); +int sbc_parse(sbc_t *sbc, void *input, int input_len); +int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *len); +int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, + int output_len, int *written); void sbc_finish(sbc_t *sbc); #ifdef __cplusplus diff --git a/sbc/sbcdec.c b/sbc/sbcdec.c index 866b844..09a211a 100644 --- a/sbc/sbcdec.c +++ b/sbc/sbcdec.c @@ -46,7 +46,7 @@ static void decode(char *filename, char *output, int tofile) struct stat st; off_t filesize; sbc_t sbc; - int fd, ad, pos, streamlen, framelen, count, written; + int fd, ad, pos, streamlen, framelen, count, written, len; int format = AFMT_S16_BE; if (stat(filename, &st) < 0) { @@ -97,7 +97,7 @@ static void decode(char *filename, char *output, int tofile) sbc_init(&sbc, 0L); sbc.swap = 1; - framelen = sbc_decode(&sbc, stream, streamlen); + framelen = sbc_decode(&sbc, stream, streamlen, buf, sizeof(buf), &len); printf("%d Hz, %d channels\n", sbc.rate, sbc.channels); if (!tofile) { if (ioctl(ad, SNDCTL_DSP_SETFMT, &format) < 0) { @@ -125,7 +125,7 @@ static void decode(char *filename, char *output, int tofile) * length of the frame we just decoded count is the number of * decoded bytes yet to be written */ - if (count + sbc.len > BUF_SIZE) { + if (count + len > BUF_SIZE) { /* buffer is too full to stuff decoded audio in so it * must be written to the device */ written = write(ad, buf, count); @@ -134,23 +134,23 @@ static void decode(char *filename, char *output, int tofile) } /* sanity check */ - if (count + sbc.len > BUF_SIZE) { + if (count + len > BUF_SIZE) { fprintf(stderr, "buffer size of %d is too small for decoded" - " data (%d)\n", BUF_SIZE, sbc.len + count); + " data (%d)\n", BUF_SIZE, len + count); exit(1); } - /* move the latest decoded data into buf and increase - * the count */ - memcpy(buf + count, sbc.data, sbc.len); - count += sbc.len; + /* increase the count */ + count += len; /* push the pointer in the file forward to the next bit to be * decoded tell the decoder to decode up to the remaining * length of the file (!) */ pos += framelen; - framelen = sbc_decode(&sbc, stream + pos, streamlen - pos); + framelen = sbc_decode(&sbc, stream + pos, streamlen - pos, + buf + count, sizeof(buf) - count, + &len); } if (count > 0) { diff --git a/sbc/sbcenc.c b/sbc/sbcenc.c index 94b9f64..cba31c7 100644 --- a/sbc/sbcenc.c +++ b/sbc/sbcenc.c @@ -104,9 +104,9 @@ static ssize_t __write(int fd, const void *buf, size_t count) static void encode(char *filename, int subbands, int joint) { struct au_header *au_hdr; - unsigned char buf[2048]; + unsigned char input[2048], output[2048]; sbc_t sbc; - int fd, len, size, count; + int fd, len, size, count, encoded; if (strcmp(filename, "-")) { fd = open(filename, O_RDONLY); @@ -118,7 +118,7 @@ static void encode(char *filename, int subbands, int joint) } else fd = fileno(stdin); - len = __read(fd, buf, sizeof(buf)); + len = __read(fd, input, sizeof(input)); if (len < sizeof(*au_hdr)) { if (fd > fileno(stderr)) fprintf(stderr, "Can't read header from file %s: %s\n", @@ -128,7 +128,7 @@ static void encode(char *filename, int subbands, int joint) goto done; } - au_hdr = (struct au_header *) buf; + au_hdr = (struct au_header *) input; if (au_hdr->magic != AU_MAGIC || BE_INT(au_hdr->hdr_size) > 128 || @@ -147,11 +147,11 @@ static void encode(char *filename, int subbands, int joint) sbc.swap = 1; count = BE_INT(au_hdr->data_size); size = len - BE_INT(au_hdr->hdr_size); - memmove(buf, buf + BE_INT(au_hdr->hdr_size), size); + memmove(input, input + BE_INT(au_hdr->hdr_size), size); while (1) { - if (size < sizeof(buf)) { - len = __read(fd, buf + size, sizeof(buf) - size); + if (size < sizeof(input)) { + len = __read(fd, input + size, sizeof(input) - size); if (len == 0) break; @@ -163,17 +163,18 @@ static void encode(char *filename, int subbands, int joint) size += len; } - len = sbc_encode(&sbc, buf, size); + len = sbc_encode(&sbc, input, size, output, sizeof(output), + &encoded); if (len < size) - memmove(buf, buf + len, size - len); + memmove(input, input + len, size - len); size -= len; - len = __write(fileno(stdout), sbc.data, sbc.len); + len = __write(fileno(stdout), output, encoded); if (len == 0) break; - if (len < 0 || len != sbc.len) { + if (len < 0 || len != encoded) { perror("Can't write SBC output"); break; }