summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDominik Wenger <domonoky@googlemail.com>2007-12-14 16:04:38 +0000
committerDominik Wenger <domonoky@googlemail.com>2007-12-14 16:04:38 +0000
commited047d9db1dcee92afb8fe6bacb5d90ccb39481e (patch)
tree163bfbbf5316f4e92315c726516515eb4f04a120 /tools
parentb2f7c61f84191d3d15606400165efe931bb66d2a (diff)
downloadrockbox-ed047d9db1dcee92afb8fe6bacb5d90ccb39481e.tar.gz
rockbox-ed047d9db1dcee92afb8fe6bacb5d90ccb39481e.tar.bz2
rockbox-ed047d9db1dcee92afb8fe6bacb5d90ccb39481e.zip
refactor rbspeex, so we build a librbspeex.a for linking into rbutil.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15924 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'tools')
-rw-r--r--tools/rbspeex/Makefile19
-rw-r--r--tools/rbspeex/rbspeex.c261
-rw-r--r--tools/rbspeex/rbspeex.h34
-rw-r--r--tools/rbspeex/rbspeexdec.c14
-rw-r--r--tools/rbspeex/rbspeexenc.c221
5 files changed, 309 insertions, 240 deletions
diff --git a/tools/rbspeex/Makefile b/tools/rbspeex/Makefile
index f6e70def96..a2b6725f5d 100644
--- a/tools/rbspeex/Makefile
+++ b/tools/rbspeex/Makefile
@@ -26,7 +26,7 @@ endif
# This sets up 'SRC' based on the files mentioned in SOURCES
SRC := $(shell cat $(SPEEXSRC)/SOURCES | $(CC) $(CFLAGS) -E -P - | grep -v "^\#")
-SOURCES = $(SRC:%.c=$(SPEEXSRC)/%.c) rbspeexenc.c rbspeexdec.c
+SOURCES = $(SRC:%.c=$(SPEEXSRC)/%.c) rbspeex.c rbspeexenc.c rbspeexdec.c
OBJS := $(SRC:%.c=%.o)
DEPFILE = dep-speex
DIRS =
@@ -49,23 +49,24 @@ $(DEPFILE): $(SOURCES)
done > $(DEPFILE); \
echo "oo" > /dev/null )
-libspeex.a: $(OBJS) $(DEPFILE)
- @echo AR libspeex.a
- $(SILENT)$(AR) ruv $@ $+ > /dev/null 2>&1
+librbspeex.a: $(OBJS) $(DEPFILE) rbspeex.o
+ @echo AR librbspeex.a
+ $(AR) ruv $@ $+ > /dev/null 2>&1
-../rbspeexenc: $(OBJS) libspeex.a rbspeexenc.o
+../rbspeexenc: $(OBJS) rbspeexenc.o librbspeex.a
@echo Linking ../rbspeexenc
- $(SILENT)$(CC) $(CFLAGS) -o ../rbspeexenc rbspeexenc.o libspeex.a -lm
+ $(SILENT)$(CC) $(CFLAGS) -o ../rbspeexenc rbspeexenc.o librbspeex.a -lm
-../rbspeexdec: $(OBJS) libspeex.a rbspeexdec.o
+../rbspeexdec: $(OBJS) librbspeex.a rbspeexdec.o
@echo Linking ../rbspeexdec
- $(SILENT)$(CC) $(CFLAGS) -o ../rbspeexdec rbspeexdec.o libspeex.a -lm
+ $(SILENT)$(CC) $(CFLAGS) -o ../rbspeexdec rbspeexdec.o librbspeex.a -lm
%.o:
@echo CC $<
$(SILENT)$(CC) $(CFLAGS) -c $< -o $@
+
clean:
- rm -f $(OBJS) libspeex.a rbspeexenc.o ../rbspeexenc dep-speex
+ rm -f $(OBJS) libspeex.a librbspeex.a rbspeexenc.o ../rbspeexenc dep-speex
-include $(DEPFILE)
diff --git a/tools/rbspeex/rbspeex.c b/tools/rbspeex/rbspeex.c
new file mode 100644
index 0000000000..e211b9606a
--- /dev/null
+++ b/tools/rbspeex/rbspeex.c
@@ -0,0 +1,261 @@
+/**************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2007 Thom Johansen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include <speex/speex.h>
+#include <speex/speex_resampler.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "rbspeex.h"
+
+/* Read an unaligned 32-bit little endian long from buffer. */
+unsigned int get_long_le(unsigned char *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+void put_ushort_le(unsigned short x, unsigned char *out)
+{
+ out[0] = x & 0xff;
+ out[1] = x >> 8;
+}
+
+void put_uint_le(unsigned int x, unsigned char *out)
+{
+ out[0] = x & 0xff;
+ out[1] = (x >> 8) & 0xff;
+ out[2] = (x >> 16) & 0xff;
+ out[3] = x >> 24;
+}
+
+
+
+bool get_wave_metadata(FILE *fd, int *numchan, int *bps, int *sr, int *numsamples)
+{
+ unsigned char buf[1024];
+ unsigned long totalsamples = 0;
+ unsigned long channels = 0;
+ unsigned long bitspersample = 0;
+ unsigned long numbytes = 0;
+ size_t read_bytes;
+ int i;
+
+ if ((read_bytes = fread(buf, 1, 12, fd)) < 12)
+ return false;
+
+ if ((memcmp(buf, "RIFF",4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0))
+ return false;
+
+ /* iterate over WAVE chunks until 'data' chunk */
+ while (1) {
+ /* get chunk header */
+ if ((read_bytes = fread(buf, 1, 8, fd)) < 8)
+ return false;
+
+ /* chunkSize */
+ i = get_long_le(&buf[4]);
+
+ if (memcmp(buf, "fmt ", 4) == 0) {
+ /* get rest of chunk */
+ if ((read_bytes = fread(buf, 1, 16, fd)) < 16)
+ return false;
+
+ i -= 16;
+
+ channels = *numchan = buf[2] | (buf[3] << 8);
+ *sr = get_long_le(&buf[4]);
+ /* wBitsPerSample */
+ bitspersample = *bps = buf[14] | (buf[15] << 8);
+ } else if (memcmp(buf, "data", 4) == 0) {
+ numbytes = i;
+ break;
+ } else if (memcmp(buf, "fact", 4) == 0) {
+ /* dwSampleLength */
+ if (i >= 4) {
+ /* get rest of chunk */
+ if ((read_bytes = fread(buf, 1, 4, fd)) < 4)
+ return false;
+
+ i -= 4;
+ totalsamples = get_long_le(buf);
+ }
+ }
+
+ /* seek to next chunk (even chunk sizes must be padded) */
+ if (i & 0x01)
+ i++;
+
+ if (fseek(fd, i, SEEK_CUR) < 0)
+ return false;
+ }
+
+ if ((numbytes == 0) || (channels == 0))
+ return false;
+
+ if (totalsamples == 0) {
+ /* for PCM only */
+ totalsamples = numbytes/((((bitspersample - 1) / 8) + 1)*channels);
+ }
+ *numsamples = totalsamples;
+ return true;
+}
+
+/* We'll eat an entire WAV file here, and encode it with Speex, packing the
+ * bits as tightly as we can. Output is completely raw, with absolutely
+ * nothing to identify the contents. Files are left open, so remember to close
+ * them.
+ */
+bool encode_file(FILE *fin, FILE *fout, float quality, int complexity,
+ bool narrowband, float volume, char *errstr, size_t errlen)
+{
+ spx_int16_t *in = NULL, *inpos;
+ spx_int16_t enc_buf[640]; /* Max frame size */
+ char cbits[200];
+ void *st = NULL;
+ SpeexResamplerState *resampler = NULL;
+ SpeexBits bits;
+ int i, tmp, target_sr, numchan, bps, sr, numsamples, frame_size, lookahead;
+ int nbytes;
+ bool ret = true;
+
+ if (!get_wave_metadata(fin, &numchan, &bps, &sr, &numsamples)) {
+ snprintf(errstr, errlen, "invalid WAV file");
+ return false;
+ }
+ if (numchan != 1) {
+ snprintf(errstr, errlen, "input file must be mono");
+ return false;
+ }
+ if (bps != 16) {
+ snprintf(errstr, errlen, "samples must be 16 bit");
+ return false;
+ }
+
+ /* Allocate an encoder of specified type, defaults to wideband */
+ st = speex_encoder_init(narrowband ? &speex_nb_mode : &speex_wb_mode);
+ if (narrowband)
+ target_sr = 8000;
+ else
+ target_sr = 16000;
+ speex_bits_init(&bits);
+
+ /* VBR */
+ tmp = 1;
+ speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
+ /* Quality, 0-10 */
+ speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &quality);
+ /* Complexity, 0-10 */
+ speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity);
+ speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
+ speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
+
+ /* Read input samples into a buffer */
+ in = calloc(numsamples + lookahead, sizeof(spx_int16_t));
+ if (in == NULL) {
+ snprintf(errstr, errlen, "could not allocate clip memory");
+ ret = false;
+ goto finish;
+ }
+ if (fread(in, 2, numsamples, fin) != numsamples) {
+ snprintf(errstr, errlen, "could not read input file data");
+ ret = false;
+ goto finish;
+ }
+
+ if (volume != 1.0f) {
+ for (i = 0; i < numsamples; ++i)
+ in[i] *= volume;
+ }
+
+ if (sr != target_sr) {
+ resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);
+ speex_resampler_skip_zeros(resampler);
+ }
+
+ /* There will be 'lookahead' samples of zero at the end of the array, to
+ * make sure the Speex encoder is allowed to spit out all its data at clip
+ * end */
+ numsamples += lookahead;
+
+ inpos = in;
+ while (numsamples > 0) {
+ int samples = frame_size;
+
+ /* Check if we need to resample */
+ if (sr != target_sr) {
+ spx_uint32_t in_len = numsamples, out_len = frame_size;
+ double resample_factor = (double)sr/(double)target_sr;
+ /* Calculate how many input samples are needed for one full frame
+ * out, and add some, just in case. */
+ spx_uint32_t samples_in = frame_size*resample_factor + 50;
+
+ /* Limit this or resampler will try to allocate it all on stack */
+ if (in_len > samples_in)
+ in_len = samples_in;
+ speex_resampler_process_int(resampler, 0, inpos, &in_len,
+ enc_buf, &out_len);
+ inpos += in_len;
+ samples = out_len;
+ numsamples -= in_len;
+ } else {
+ if (samples > numsamples)
+ samples = numsamples;
+ memcpy(enc_buf, inpos, samples*2);
+ inpos += frame_size;
+ numsamples -= frame_size;
+ }
+ /* Pad out with zeros if we didn't fill all input */
+ memset(enc_buf + samples, 0, (frame_size - samples)*2);
+
+ if (speex_encode_int(st, enc_buf, &bits) < 0) {
+ snprintf(errstr, errlen, "encoder error");
+ ret = false;
+ goto finish;
+ }
+
+ /* Copy the bits to an array of char that can be written */
+ nbytes = speex_bits_write_whole_bytes(&bits, cbits, 200);
+
+ /* Write the compressed data */
+ if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
+ snprintf(errstr, errlen, "could not write output data");
+ ret = false;
+ goto finish;
+ }
+ }
+ /* Squeeze out the last bits */
+ nbytes = speex_bits_write(&bits, cbits, 200);
+ if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
+ snprintf(errstr, errlen, "could not write output data");
+ ret = false;
+ }
+
+finish:
+ if (st != NULL)
+ speex_encoder_destroy(st);
+ speex_bits_destroy(&bits);
+ if (resampler != NULL)
+ speex_resampler_destroy(resampler);
+ if (in != NULL)
+ free(in);
+ return ret;
+}
+
+
diff --git a/tools/rbspeex/rbspeex.h b/tools/rbspeex/rbspeex.h
new file mode 100644
index 0000000000..00d045c74a
--- /dev/null
+++ b/tools/rbspeex/rbspeex.h
@@ -0,0 +1,34 @@
+/**************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2007 Thom Johansen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifndef RBSPEEX_H
+#define RBSPEEX_H
+
+#include <stdbool.h>
+
+unsigned int get_long_le(unsigned char *p);
+bool get_wave_metadata(FILE *fd, int *numchan, int *bps, int *sr, int *numsamples);
+bool encode_file(FILE *fin, FILE *fout, float quality, int complexity,
+ bool narrowband, float volume, char *errstr, size_t errlen);
+
+void put_ushort_le(unsigned short x, unsigned char *out);
+void put_uint_le(unsigned int x, unsigned char *out);
+
+
+#endif
+
diff --git a/tools/rbspeex/rbspeexdec.c b/tools/rbspeex/rbspeexdec.c
index 90562f7309..a29361da3a 100644
--- a/tools/rbspeex/rbspeexdec.c
+++ b/tools/rbspeex/rbspeexdec.c
@@ -20,25 +20,13 @@
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
+#include "rbspeex.h"
#define USAGE_TEXT \
"Usage: rbspeexdec infile outfile\n"\
"rbspeexdec outputs mono 16 bit 16 kHz WAV files.\n"\
"WARNING: This tool will only decode files made with rbspeexenc!\n"
-void put_ushort_le(unsigned short x, unsigned char *out)
-{
- out[0] = x & 0xff;
- out[1] = x >> 8;
-}
-
-void put_uint_le(unsigned int x, unsigned char *out)
-{
- out[0] = x & 0xff;
- out[1] = (x >> 8) & 0xff;
- out[2] = (x >> 16) & 0xff;
- out[3] = x >> 24;
-}
int main(int argc, char **argv)
{
diff --git a/tools/rbspeex/rbspeexenc.c b/tools/rbspeex/rbspeexenc.c
index e919bc8990..c7ea6e429a 100644
--- a/tools/rbspeex/rbspeexenc.c
+++ b/tools/rbspeex/rbspeexenc.c
@@ -16,13 +16,13 @@
*
***************************************************************************/
-#include <speex/speex.h>
-#include <speex/speex_resampler.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include "rbspeex.h"
+
#define USAGE_TEXT \
"Usage: rbspeexenc [options] infile outfile\n"\
"Options:\n"\
@@ -35,222 +35,6 @@
"to either 16 kHz by default, or 8 kHz if narrowband mode is enabled.\n"\
"WARNING: This tool will create files that are only usable by Rockbox!\n"
-/* Read an unaligned 32-bit little endian long from buffer. */
-unsigned int get_long_le(unsigned char *p)
-{
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-bool get_wave_metadata(FILE *fd, int *numchan, int *bps, int *sr, int *numsamples)
-{
- unsigned char buf[1024];
- unsigned long totalsamples = 0;
- unsigned long channels = 0;
- unsigned long bitspersample = 0;
- unsigned long numbytes = 0;
- size_t read_bytes;
- int i;
-
- if ((read_bytes = fread(buf, 1, 12, fd)) < 12)
- return false;
-
- if ((memcmp(buf, "RIFF",4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0))
- return false;
-
- /* iterate over WAVE chunks until 'data' chunk */
- while (1) {
- /* get chunk header */
- if ((read_bytes = fread(buf, 1, 8, fd)) < 8)
- return false;
-
- /* chunkSize */
- i = get_long_le(&buf[4]);
-
- if (memcmp(buf, "fmt ", 4) == 0) {
- /* get rest of chunk */
- if ((read_bytes = fread(buf, 1, 16, fd)) < 16)
- return false;
-
- i -= 16;
-
- channels = *numchan = buf[2] | (buf[3] << 8);
- *sr = get_long_le(&buf[4]);
- /* wBitsPerSample */
- bitspersample = *bps = buf[14] | (buf[15] << 8);
- } else if (memcmp(buf, "data", 4) == 0) {
- numbytes = i;
- break;
- } else if (memcmp(buf, "fact", 4) == 0) {
- /* dwSampleLength */
- if (i >= 4) {
- /* get rest of chunk */
- if ((read_bytes = fread(buf, 1, 4, fd)) < 4)
- return false;
-
- i -= 4;
- totalsamples = get_long_le(buf);
- }
- }
-
- /* seek to next chunk (even chunk sizes must be padded) */
- if (i & 0x01)
- i++;
-
- if (fseek(fd, i, SEEK_CUR) < 0)
- return false;
- }
-
- if ((numbytes == 0) || (channels == 0))
- return false;
-
- if (totalsamples == 0) {
- /* for PCM only */
- totalsamples = numbytes/((((bitspersample - 1) / 8) + 1)*channels);
- }
- *numsamples = totalsamples;
- return true;
-}
-
-/* We'll eat an entire WAV file here, and encode it with Speex, packing the
- * bits as tightly as we can. Output is completely raw, with absolutely
- * nothing to identify the contents. Files are left open, so remember to close
- * them.
- */
-bool encode_file(FILE *fin, FILE *fout, float quality, int complexity,
- bool narrowband, float volume, char *errstr, size_t errlen)
-{
- spx_int16_t *in = NULL, *inpos;
- spx_int16_t enc_buf[640]; /* Max frame size */
- char cbits[200];
- void *st = NULL;
- SpeexResamplerState *resampler = NULL;
- SpeexBits bits;
- int i, tmp, target_sr, numchan, bps, sr, numsamples, frame_size, lookahead;
- int nbytes;
- bool ret = true;
-
- if (!get_wave_metadata(fin, &numchan, &bps, &sr, &numsamples)) {
- snprintf(errstr, errlen, "invalid WAV file");
- return false;
- }
- if (numchan != 1) {
- snprintf(errstr, errlen, "input file must be mono");
- return false;
- }
- if (bps != 16) {
- snprintf(errstr, errlen, "samples must be 16 bit");
- return false;
- }
-
- /* Allocate an encoder of specified type, defaults to wideband */
- st = speex_encoder_init(narrowband ? &speex_nb_mode : &speex_wb_mode);
- if (narrowband)
- target_sr = 8000;
- else
- target_sr = 16000;
- speex_bits_init(&bits);
-
- /* VBR */
- tmp = 1;
- speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
- /* Quality, 0-10 */
- speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &quality);
- /* Complexity, 0-10 */
- speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity);
- speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
- speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
-
- /* Read input samples into a buffer */
- in = calloc(numsamples + lookahead, sizeof(spx_int16_t));
- if (in == NULL) {
- snprintf(errstr, errlen, "could not allocate clip memory");
- ret = false;
- goto finish;
- }
- if (fread(in, 2, numsamples, fin) != numsamples) {
- snprintf(errstr, errlen, "could not read input file data");
- ret = false;
- goto finish;
- }
-
- if (volume != 1.0f) {
- for (i = 0; i < numsamples; ++i)
- in[i] *= volume;
- }
-
- if (sr != target_sr) {
- resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);
- speex_resampler_skip_zeros(resampler);
- }
-
- /* There will be 'lookahead' samples of zero at the end of the array, to
- * make sure the Speex encoder is allowed to spit out all its data at clip
- * end */
- numsamples += lookahead;
-
- inpos = in;
- while (numsamples > 0) {
- int samples = frame_size;
-
- /* Check if we need to resample */
- if (sr != target_sr) {
- spx_uint32_t in_len = numsamples, out_len = frame_size;
- double resample_factor = (double)sr/(double)target_sr;
- /* Calculate how many input samples are needed for one full frame
- * out, and add some, just in case. */
- spx_uint32_t samples_in = frame_size*resample_factor + 50;
-
- /* Limit this or resampler will try to allocate it all on stack */
- if (in_len > samples_in)
- in_len = samples_in;
- speex_resampler_process_int(resampler, 0, inpos, &in_len,
- enc_buf, &out_len);
- inpos += in_len;
- samples = out_len;
- numsamples -= in_len;
- } else {
- if (samples > numsamples)
- samples = numsamples;
- memcpy(enc_buf, inpos, samples*2);
- inpos += frame_size;
- numsamples -= frame_size;
- }
- /* Pad out with zeros if we didn't fill all input */
- memset(enc_buf + samples, 0, (frame_size - samples)*2);
-
- if (speex_encode_int(st, enc_buf, &bits) < 0) {
- snprintf(errstr, errlen, "encoder error");
- ret = false;
- goto finish;
- }
-
- /* Copy the bits to an array of char that can be written */
- nbytes = speex_bits_write_whole_bytes(&bits, cbits, 200);
-
- /* Write the compressed data */
- if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
- snprintf(errstr, errlen, "could not write output data");
- ret = false;
- goto finish;
- }
- }
- /* Squeeze out the last bits */
- nbytes = speex_bits_write(&bits, cbits, 200);
- if (fwrite(cbits, 1, nbytes, fout) != nbytes) {
- snprintf(errstr, errlen, "could not write output data");
- ret = false;
- }
-
-finish:
- if (st != NULL)
- speex_encoder_destroy(st);
- speex_bits_destroy(&bits);
- if (resampler != NULL)
- speex_resampler_destroy(resampler);
- if (in != NULL)
- free(in);
- return ret;
-}
int main(int argc, char **argv)
{
@@ -308,3 +92,4 @@ int main(int argc, char **argv)
}
return 0;
}
+