summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.alt23
-rw-r--r--test/Makefile.am32
-rw-r--r--test/amrnb-dec.c (renamed from test/amrnb-dec.cpp)44
-rw-r--r--test/amrnb-enc-sine.c59
-rw-r--r--test/amrnb-enc.c121
-rw-r--r--test/amrwb-dec.c (renamed from test/amrwb-dec.cpp)46
-rw-r--r--test/linkboth.c8
-rw-r--r--test/wav.cpp87
-rw-r--r--test/wavreader.c162
-rw-r--r--test/wavreader.h (renamed from test/wav.h)34
-rw-r--r--test/wavwriter.c111
-rw-r--r--test/wavwriter.h36
12 files changed, 566 insertions, 197 deletions
diff --git a/test/Makefile.alt b/test/Makefile.alt
deleted file mode 100644
index afab10e..0000000
--- a/test/Makefile.alt
+++ /dev/null
@@ -1,23 +0,0 @@
-CFLAGS = -Wall -pedantic -I../amrnb -I../amrwb
-CXXFLAGS = $(CFLAGS)
-LDFLAGS = -L../amrnb -L../amrwb
-
-all: amrnb-dec amrnb-enc amrwb-dec
-
-amrnb-dec: amrnb-dec.o wav.o
- $(CXX) -o $@ $+ $(LDFLAGS) -lopencore-amrnb
-
-amrnb-enc: amrnb-enc.o
- $(CC) -o $@ $+ $(LDFLAGS) -lm -lopencore-amrnb
-
-amrwb-dec: amrwb-dec.o wav.o
- $(CXX) -o $@ $+ $(LDFLAGS) -lopencore-amrwb
-
-# To check that both libraries can be linked in statically at the same
-# time without duplicate symbols
-linkboth: linkboth.o
- $(CC) -static -o $@ $+ $(LDFLAGS) -lopencore-amrnb -lopencore-amrwb
-
-clean:
- rm -f amrnb-dec amrnb-enc amrwb-dec linkboth *.o out.wav out.amr
-
diff --git a/test/Makefile.am b/test/Makefile.am
index 63e9b3f..a0c4ffa 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,23 +1,35 @@
-noinst_PROGRAMS = amrnb-dec$(EXEEXT) amrnb-enc$(EXEEXT) amrwb-dec$(EXEEXT) linkboth$(EXEEXT)
-
-EXTRA_DIST = Makefile.alt
+bin_PROGRAMS = amrwb-dec$(EXEEXT)
+noinst_PROGRAMS = linkboth$(EXEEXT)
+AM_CFLAGS =
+
+if AMRNB_DECODER
+ bin_PROGRAMS += amrnb-dec$(EXEEXT)
+else
+ AM_CFLAGS += -DDISABLE_AMRNB_DECODER
+endif
+if AMRNB_ENCODER
+ bin_PROGRAMS += amrnb-enc$(EXEEXT)
+ noinst_PROGRAMS += amrnb-enc-sine$(EXEEXT)
+else
+ AM_CFLAGS += -DDISABLE_AMRNB_ENCODER
+endif
INCLUDES = -I$(top_srcdir)/amrnb -I$(top_srcdir)/amrwb
-CLEANFILES = out.amr out.wav
-
amrnb_dec_LDADD = $(top_builddir)/amrnb/libopencore-amrnb.la
amrnb_enc_LDADD = $(top_builddir)/amrnb/libopencore-amrnb.la
-amrnb_enc_LDFLAGS = -lm
+amrnb_enc_sine_LDADD = $(top_builddir)/amrnb/libopencore-amrnb.la
+amrnb_enc_sine_LDFLAGS = -lm
amrwb_dec_LDADD = $(top_builddir)/amrwb/libopencore-amrwb.la
linkboth_LDFLAGS = -static
linkboth_LDADD = $(top_builddir)/amrnb/libopencore-amrnb.la $(top_builddir)/amrwb/libopencore-amrwb.la
-amrnb_dec_SOURCES = amrnb-dec.cpp wav.cpp
-amrnb_enc_SOURCES = amrnb-enc.c
-amrwb_dec_SOURCES = amrwb-dec.cpp wav.cpp
+amrnb_dec_SOURCES = amrnb-dec.c wavwriter.c
+amrnb_enc_SOURCES = amrnb-enc.c wavreader.c
+amrnb_enc_sine_SOURCES = amrnb-enc-sine.c
+amrwb_dec_SOURCES = amrwb-dec.c wavwriter.c
linkboth_SOURCES = linkboth.c
-noinst_HEADERS = wav.h
+noinst_HEADERS = wavwriter.h wavreader.h
diff --git a/test/amrnb-dec.cpp b/test/amrnb-dec.c
index 98a352d..f558392 100644
--- a/test/amrnb-dec.cpp
+++ b/test/amrnb-dec.c
@@ -19,65 +19,69 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
-#include "wav.h"
-extern "C" {
+#include "wavwriter.h"
#include <interf_dec.h>
-}
/* From WmfDecBytesPerFrame in dec_input_format_tab.cpp */
const int sizes[] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 6, 5, 5, 0, 0, 0, 0 };
int main(int argc, char *argv[]) {
- if (argc < 2) {
- fprintf(stderr, "%s in.amr\n", argv[0]);
+ FILE* in;
+ char header[6];
+ int n;
+ void *wav, *amr;
+ if (argc < 3) {
+ fprintf(stderr, "%s in.amr out.wav\n", argv[0]);
return 1;
}
- FILE* in = fopen(argv[1], "rb");
+ in = fopen(argv[1], "rb");
if (!in) {
perror(argv[1]);
return 1;
}
- char header[6];
- int n = fread(header, 1, 6, in);
+ n = fread(header, 1, 6, in);
if (n != 6 || memcmp(header, "#!AMR\n", 6)) {
fprintf(stderr, "Bad header\n");
return 1;
}
- WavWriter wav("out.wav", 8000, 16, 1);
+ wav = wav_write_open(argv[2], 8000, 16, 1);
+ if (!wav) {
+ fprintf(stderr, "Unable to open %s\n", argv[2]);
+ return 1;
+ }
- void* amr = Decoder_Interface_init();
- while (true) {
- uint8_t buffer[500];
+ amr = Decoder_Interface_init();
+ while (1) {
+ uint8_t buffer[500], littleendian[320], *ptr;
+ int size, i;
+ int16_t outbuffer[160];
/* Read the mode byte */
n = fread(buffer, 1, 1, in);
if (n <= 0)
break;
/* Find the packet size */
- int size = sizes[(buffer[0] >> 3) & 0x0f];
- if (size <= 0)
- break;
+ size = sizes[(buffer[0] >> 3) & 0x0f];
n = fread(buffer + 1, 1, size, in);
if (n != size)
break;
/* Decode the packet */
- int16_t outbuffer[160];
Decoder_Interface_Decode(amr, buffer, outbuffer, 0);
/* Convert to little endian and write to wav */
- uint8_t littleendian[320];
- uint8_t* ptr = littleendian;
- for (int i = 0; i < 160; i++) {
+ ptr = littleendian;
+ for (i = 0; i < 160; i++) {
*ptr++ = (outbuffer[i] >> 0) & 0xff;
*ptr++ = (outbuffer[i] >> 8) & 0xff;
}
- wav.writeData(littleendian, 320);
+ wav_write_data(wav, littleendian, 320);
}
fclose(in);
Decoder_Interface_exit(amr);
+ wav_write_close(wav);
return 0;
}
diff --git a/test/amrnb-enc-sine.c b/test/amrnb-enc-sine.c
new file mode 100644
index 0000000..51c04b2
--- /dev/null
+++ b/test/amrnb-enc-sine.c
@@ -0,0 +1,59 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2009 Martin Storsjo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <math.h>
+#include <interf_enc.h>
+
+int main(int argc, char *argv[]) {
+ int i, j;
+ void* amr;
+ FILE* out;
+ int sample_pos = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "%s out.amr\n", argv[0]);
+ return 1;
+ }
+
+ amr = Encoder_Interface_init(0);
+ out = fopen(argv[1], "wb");
+ if (!out) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ fwrite("#!AMR\n", 1, 6, out);
+ for (i = 0; i < 1000; i++) {
+ short buf[160];
+ uint8_t outbuf[500];
+ int n;
+ for (j = 0; j < 160; j++) {
+ buf[j] = 32767*sin(440*2*3.141592654*sample_pos/8000);
+ sample_pos++;
+ }
+ n = Encoder_Interface_Encode(amr, MR475, buf, outbuf, 0);
+ fwrite(outbuf, 1, n, out);
+ }
+ fclose(out);
+ Encoder_Interface_exit(amr);
+
+ return 0;
+}
+
diff --git a/test/amrnb-enc.c b/test/amrnb-enc.c
index 9a16098..6fc5d40 100644
--- a/test/amrnb-enc.c
+++ b/test/amrnb-enc.c
@@ -18,32 +18,127 @@
#include <stdio.h>
#include <stdint.h>
-#include <math.h>
#include <interf_enc.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "wavreader.h"
+
+void usage(const char* name) {
+ fprintf(stderr, "%s [-r bitrate] [-d] in.wav out.amr\n", name);
+}
+
+enum Mode findMode(const char* str) {
+ struct {
+ enum Mode mode;
+ int rate;
+ } modes[] = {
+ { MR475, 4750 },
+ { MR515, 5150 },
+ { MR59, 5900 },
+ { MR67, 6700 },
+ { MR74, 7400 },
+ { MR795, 7950 },
+ { MR102, 10200 },
+ { MR122, 12200 }
+ };
+ int rate = atoi(str);
+ int closest = -1;
+ int closestdiff = 0;
+ unsigned int i;
+ for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
+ if (modes[i].rate == rate)
+ return modes[i].mode;
+ if (closest < 0 || closestdiff > abs(modes[i].rate - rate)) {
+ closest = i;
+ closestdiff = abs(modes[i].rate - rate);
+ }
+ }
+ fprintf(stderr, "Using bitrate %d\n", modes[closest].rate);
+ return modes[closest].mode;
+}
int main(int argc, char *argv[]) {
- int i, j;
- void* amr;
- FILE* out;
- int sample_pos = 0;
+ enum Mode mode = MR122;
+ int ch, dtx = 0;
+ const char *infile, *outfile;
+ FILE *out;
+ void *wav, *amr;
+ int format, sampleRate, channels, bitsPerSample;
+ int inputSize;
+ uint8_t* inputBuf;
+ while ((ch = getopt(argc, argv, "r:d")) != -1) {
+ switch (ch) {
+ case 'r':
+ mode = findMode(optarg);
+ break;
+ case 'd':
+ dtx = 1;
+ break;
+ case '?':
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ if (argc - optind < 2) {
+ usage(argv[0]);
+ return 1;
+ }
+ infile = argv[optind];
+ outfile = argv[optind + 1];
- amr = Encoder_Interface_init(0);
- out = fopen("out.amr", "wb");
+ wav = wav_read_open(infile);
+ if (!wav) {
+ fprintf(stderr, "Unable to open wav file %s\n", infile);
+ return 1;
+ }
+ if (!wav_get_header(wav, &format, &channels, &sampleRate, &bitsPerSample, NULL)) {
+ fprintf(stderr, "Bad wav file %s\n", infile);
+ return 1;
+ }
+ if (format != 1) {
+ fprintf(stderr, "Unsupported WAV format %d\n", format);
+ return 1;
+ }
+ if (bitsPerSample != 16) {
+ fprintf(stderr, "Unsupported WAV sample depth %d\n", bitsPerSample);
+ return 1;
+ }
+ if (channels != 1)
+ fprintf(stderr, "Warning, only compressing one audio channel\n");
+ if (sampleRate != 8000)
+ fprintf(stderr, "Warning, AMR-NB uses 8000 Hz sample rate (WAV file has %d Hz)\n", sampleRate);
+ inputSize = channels*2*160;
+ inputBuf = (uint8_t*) malloc(inputSize);
+
+ amr = Encoder_Interface_init(dtx);
+ out = fopen(outfile, "wb");
+ if (!out) {
+ perror(outfile);
+ return 1;
+ }
fwrite("#!AMR\n", 1, 6, out);
- for (i = 0; i < 1000; i++) {
+ while (1) {
short buf[160];
uint8_t outbuf[500];
- int n;
- for (j = 0; j < 160; j++) {
- buf[j] = 32767*sin(440*2*3.141592654*sample_pos/8000);
- sample_pos++;
+ int read, i, n;
+ read = wav_read_data(wav, inputBuf, inputSize);
+ read /= channels;
+ read /= 2;
+ if (read < 160)
+ break;
+ for (i = 0; i < 160; i++) {
+ const uint8_t* in = &inputBuf[2*channels*i];
+ buf[i] = in[0] | (in[1] << 8);
}
- n = Encoder_Interface_Encode(amr, MR475, buf, outbuf, 0);
+ n = Encoder_Interface_Encode(amr, mode, buf, outbuf, 0);
fwrite(outbuf, 1, n, out);
}
+ free(inputBuf);
fclose(out);
Encoder_Interface_exit(amr);
+ wav_read_close(wav);
return 0;
}
diff --git a/test/amrwb-dec.cpp b/test/amrwb-dec.c
index 740181d..7a121e8 100644
--- a/test/amrwb-dec.cpp
+++ b/test/amrwb-dec.c
@@ -19,63 +19,69 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
-#include "wav.h"
-extern "C" {
+#include "wavwriter.h"
#include <dec_if.h>
-}
/* From pvamrwbdecoder_api.h, by dividing by 8 and rounding up */
-const int sizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, -1, -1 };
+const int sizes[] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, -1, 0 };
int main(int argc, char *argv[]) {
- if (argc < 2) {
- fprintf(stderr, "%s in.amr\n", argv[0]);
+ FILE* in;
+ char header[9];
+ int n;
+ void *wav, *amr;
+ if (argc < 3) {
+ fprintf(stderr, "%s in.amr out.wav\n", argv[0]);
return 1;
}
- FILE* in = fopen(argv[1], "rb");
+ in = fopen(argv[1], "rb");
if (!in) {
perror(argv[1]);
return 1;
}
- char header[9];
- int n = fread(header, 1, 9, in);
+ n = fread(header, 1, 9, in);
if (n != 9 || memcmp(header, "#!AMR-WB\n", 9)) {
fprintf(stderr, "Bad header\n");
return 1;
}
- WavWriter wav("out.wav", 16000, 16, 1);
- void* amr = D_IF_init();
- while (true) {
- uint8_t buffer[500];
+ wav = wav_write_open(argv[2], 16000, 16, 1);
+ if (!wav) {
+ fprintf(stderr, "Unable to open %s\n", argv[2]);
+ return 1;
+ }
+ amr = D_IF_init();
+ while (1) {
+ uint8_t buffer[500], littleendian[640], *ptr;
+ int size, i;
+ int16_t outbuffer[320];
/* Read the mode byte */
n = fread(buffer, 1, 1, in);
if (n <= 0)
break;
/* Find the packet size */
- int size = sizes[(buffer[0] >> 3) & 0x0f];
- if (size <= 0)
+ size = sizes[(buffer[0] >> 3) & 0x0f];
+ if (size < 0)
break;
n = fread(buffer + 1, 1, size, in);
if (n != size)
break;
/* Decode the packet */
- int16_t outbuffer[320];
D_IF_decode(amr, buffer, outbuffer, 0);
/* Convert to little endian and write to wav */
- uint8_t littleendian[640];
- uint8_t* ptr = littleendian;
- for (int i = 0; i < 320; i++) {
+ ptr = littleendian;
+ for (i = 0; i < 320; i++) {
*ptr++ = (outbuffer[i] >> 0) & 0xff;
*ptr++ = (outbuffer[i] >> 8) & 0xff;
}
- wav.writeData(littleendian, 640);
+ wav_write_data(wav, littleendian, 640);
}
fclose(in);
D_IF_exit(amr);
+ wav_write_close(wav);
return 0;
}
diff --git a/test/linkboth.c b/test/linkboth.c
index d2345ae..26a3f35 100644
--- a/test/linkboth.c
+++ b/test/linkboth.c
@@ -24,11 +24,15 @@
#include <dec_if.h>
int main(int argc, char *argv[]) {
+#ifndef DISABLE_AMRNB_DECODER
void* amrnb = Decoder_Interface_init();
- void* amrnb_enc = Encoder_Interface_init(0);
- void* amrwb = D_IF_init();
Decoder_Interface_exit(amrnb);
+#endif
+#ifndef DISABLE_AMRNB_ENCODER
+ void* amrnb_enc = Encoder_Interface_init(0);
Encoder_Interface_exit(amrnb_enc);
+#endif
+ void* amrwb = D_IF_init();
D_IF_exit(amrwb);
return 0;
}
diff --git a/test/wav.cpp b/test/wav.cpp
deleted file mode 100644
index fb3f015..0000000
--- a/test/wav.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 2009 Martin Storsjo
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- * -------------------------------------------------------------------
- */
-
-#include "wav.h"
-
-void WavWriter::writeString(const char *str) {
- fputc(str[0], wav);
- fputc(str[1], wav);
- fputc(str[2], wav);
- fputc(str[3], wav);
-}
-
-void WavWriter::writeInt32(int value) {
- fputc((value >> 0) & 0xff, wav);
- fputc((value >> 8) & 0xff, wav);
- fputc((value >> 16) & 0xff, wav);
- fputc((value >> 24) & 0xff, wav);
-}
-
-void WavWriter::writeInt16(int value) {
- fputc((value >> 0) & 0xff, wav);
- fputc((value >> 8) & 0xff, wav);
-}
-
-void WavWriter::writeHeader(int length) {
- writeString("RIFF");
- writeInt32(4 + 8 + 16 + 8 + length);
- writeString("WAVE");
-
- writeString("fmt ");
- writeInt32(16);
-
- int bytesPerFrame = bitsPerSample/8*channels;
- int bytesPerSec = bytesPerFrame*sampleRate;
- writeInt16(1); // Format
- writeInt16(channels); // Channels
- writeInt32(sampleRate); // Samplerate
- writeInt32(bytesPerSec); // Bytes per sec
- writeInt16(bytesPerFrame); // Bytes per frame
- writeInt16(bitsPerSample); // Bits per sample
-
- writeString("data");
- writeInt32(length);
-}
-
-WavWriter::WavWriter(const char *filename, int sampleRate, int bitsPerSample, int channels) {
- wav = fopen(filename, "wb");
- if (wav == NULL)
- return;
- dataLength = 0;
- this->sampleRate = sampleRate;
- this->bitsPerSample = bitsPerSample;
- this->channels = channels;
-
- writeHeader(dataLength);
-}
-
-WavWriter::~WavWriter() {
- if (wav == NULL)
- return;
- fseek(wav, 0, SEEK_SET);
- writeHeader(dataLength);
- fclose(wav);
-}
-
-void WavWriter::writeData(const unsigned char* data, int length) {
- if (wav == NULL)
- return;
- fwrite(data, length, 1, wav);
- dataLength += length;
-}
-
diff --git a/test/wavreader.c b/test/wavreader.c
new file mode 100644
index 0000000..55d2ab9
--- /dev/null
+++ b/test/wavreader.c
@@ -0,0 +1,162 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2009 Martin Storsjo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#include "wavreader.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+
+struct wav_reader {
+ FILE *wav;
+ uint32_t data_length;
+
+ int format;
+ int sample_rate;
+ int bits_per_sample;
+ int channels;
+ int byte_rate;
+ int block_align;
+};
+
+static uint32_t read_tag(struct wav_reader* wr) {
+ uint32_t tag = 0;
+ tag = (tag << 8) | fgetc(wr->wav);
+ tag = (tag << 8) | fgetc(wr->wav);
+ tag = (tag << 8) | fgetc(wr->wav);
+ tag = (tag << 8) | fgetc(wr->wav);
+ return tag;
+}
+
+static uint32_t read_int32(struct wav_reader* wr) {
+ uint32_t value = 0;
+ value |= fgetc(wr->wav) << 0;
+ value |= fgetc(wr->wav) << 8;
+ value |= fgetc(wr->wav) << 16;
+ value |= fgetc(wr->wav) << 24;
+ return value;
+}
+
+static uint16_t read_int16(struct wav_reader* wr) {
+ uint16_t value = 0;
+ value |= fgetc(wr->wav) << 0;
+ value |= fgetc(wr->wav) << 8;
+ return value;
+}
+
+void* wav_read_open(const char *filename) {
+ struct wav_reader* wr = (struct wav_reader*) malloc(sizeof(*wr));
+ long data_pos = 0;
+ memset(wr, 0, sizeof(*wr));
+
+ wr->wav = fopen(filename, "rb");
+ if (wr->wav == NULL) {
+ free(wr);
+ return NULL;
+ }
+
+ while (1) {
+ uint32_t tag, tag2, length;
+ tag = read_tag(wr);
+ if (feof(wr->wav))
+ break;
+ length = read_int32(wr);
+ if (tag != TAG('R', 'I', 'F', 'F') || length < 4) {
+ fseek(wr->wav, length, SEEK_CUR);
+ continue;
+ }
+ tag2 = read_tag(wr);
+ length -= 4;
+ if (tag2 != TAG('W', 'A', 'V', 'E')) {
+ fseek(wr->wav, length, SEEK_CUR);
+ continue;
+ }
+ // RIFF chunk found, iterate through it
+ while (length >= 8) {
+ uint32_t subtag, sublength;
+ subtag = read_tag(wr);
+ if (feof(wr->wav))
+ break;
+ sublength = read_int32(wr);
+ length -= 8;
+ if (length < sublength)
+ break;
+ if (subtag == TAG('f', 'm', 't', ' ')) {
+ if (sublength < 16) {
+ // Insufficient data for 'fmt '
+ break;
+ }
+ wr->format = read_int16(wr);
+ wr->channels = read_int16(wr);
+ wr->sample_rate = read_int32(wr);
+ wr->byte_rate = read_int32(wr);
+ wr->block_align = read_int16(wr);
+ wr->bits_per_sample = read_int16(wr);
+ } else if (subtag == TAG('d', 'a', 't', 'a')) {
+ data_pos = ftell(wr->wav);
+ wr->data_length = sublength;
+ fseek(wr->wav, sublength, SEEK_CUR);
+ } else {
+ fseek(wr->wav, sublength, SEEK_CUR);
+ }
+ length -= sublength;
+ }
+ if (length > 0) {
+ // Bad chunk?
+ fseek(wr->wav, length, SEEK_CUR);
+ }
+ }
+ fseek(wr->wav, data_pos, SEEK_SET);
+ return wr;
+}
+
+void wav_read_close(void* obj) {
+ struct wav_reader* wr = (struct wav_reader*) obj;
+ fclose(wr->wav);
+ free(wr);
+}
+
+int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length) {
+ struct wav_reader* wr = (struct wav_reader*) obj;
+ if (format)
+ *format = wr->format;
+ if (channels)
+ *channels = wr->channels;
+ if (sample_rate)
+ *sample_rate = wr->sample_rate;
+ if (bits_per_sample)
+ *bits_per_sample = wr->bits_per_sample;
+ if (data_length)
+ *data_length = wr->data_length;
+ return wr->format && wr->sample_rate;
+}
+
+int wav_read_data(void* obj, unsigned char* data, unsigned int length) {
+ struct wav_reader* wr = (struct wav_reader*) obj;
+ int n;
+ if (wr->wav == NULL)
+ return -1;
+ if (length > wr->data_length)
+ length = wr->data_length;
+ n = fread(data, 1, length, wr->wav);
+ wr->data_length -= length;
+ return n;
+}
+
diff --git a/test/wav.h b/test/wavreader.h
index ae77383..57a13ff 100644
--- a/test/wav.h
+++ b/test/wavreader.h
@@ -16,32 +16,22 @@
* -------------------------------------------------------------------
*/
-#ifndef WAV_H
-#define WAV_H
+#ifndef WAVREADER_H
+#define WAVREADER_H
-#include <stdio.h>
-
-class WavWriter {
-public:
- WavWriter(const char *filename, int sampleRate, int bitsPerSample, int channels);
- ~WavWriter();
-
- void writeData(const unsigned char* data, int length);
-
-private:
- void writeString(const char *str);
- void writeInt32(int value);
- void writeInt16(int value);
+#ifdef __cplusplus
+extern "C" {
+#endif
- void writeHeader(int length);
+void* wav_read_open(const char *filename);
+void wav_read_close(void* obj);
- FILE *wav;
- int dataLength;
+int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length);
+int wav_read_data(void* obj, unsigned char* data, unsigned int length);
- int sampleRate;
- int bitsPerSample;
- int channels;
-};
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/test/wavwriter.c b/test/wavwriter.c
new file mode 100644
index 0000000..3df9914
--- /dev/null
+++ b/test/wavwriter.c
@@ -0,0 +1,111 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2009 Martin Storsjo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#include "wavwriter.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct wav_writer {
+ FILE *wav;
+ int data_length;
+
+ int sample_rate;
+ int bits_per_sample;
+ int channels;
+};
+
+static void write_string(struct wav_writer* ww, const char *str) {
+ fputc(str[0], ww->wav);
+ fputc(str[1], ww->wav);
+ fputc(str[2], ww->wav);
+ fputc(str[3], ww->wav);
+}
+
+static void write_int32(struct wav_writer* ww, int value) {
+ fputc((value >> 0) & 0xff, ww->wav);
+ fputc((value >> 8) & 0xff, ww->wav);
+ fputc((value >> 16) & 0xff, ww->wav);
+ fputc((value >> 24) & 0xff, ww->wav);
+}
+
+static void write_int16(struct wav_writer* ww, int value) {
+ fputc((value >> 0) & 0xff, ww->wav);
+ fputc((value >> 8) & 0xff, ww->wav);
+}
+
+static void write_header(struct wav_writer* ww, int length) {
+ int bytes_per_frame, bytes_per_sec;
+ write_string(ww, "RIFF");
+ write_int32(ww, 4 + 8 + 16 + 8 + length);
+ write_string(ww, "WAVE");
+
+ write_string(ww, "fmt ");
+ write_int32(ww, 16);
+
+ bytes_per_frame = ww->bits_per_sample/8*ww->channels;
+ bytes_per_sec = bytes_per_frame*ww->sample_rate;
+ write_int16(ww, 1); // Format
+ write_int16(ww, ww->channels); // Channels
+ write_int32(ww, ww->sample_rate); // Samplerate
+ write_int32(ww, bytes_per_sec); // Bytes per sec
+ write_int16(ww, bytes_per_frame); // Bytes per frame
+ write_int16(ww, ww->bits_per_sample); // Bits per sample
+
+ write_string(ww, "data");
+ write_int32(ww, length);
+}
+
+void* wav_write_open(const char *filename, int sample_rate, int bits_per_sample, int channels) {
+ struct wav_writer* ww = (struct wav_writer*) malloc(sizeof(*ww));
+ memset(ww, 0, sizeof(*ww));
+ ww->wav = fopen(filename, "wb");
+ if (ww->wav == NULL) {
+ free(ww);
+ return NULL;
+ }
+ ww->data_length = 0;
+ ww->sample_rate = sample_rate;
+ ww->bits_per_sample = bits_per_sample;
+ ww->channels = channels;
+
+ write_header(ww, ww->data_length);
+ return ww;
+}
+
+void wav_write_close(void* obj) {
+ struct wav_writer* ww = (struct wav_writer*) obj;
+ if (ww->wav == NULL) {
+ free(ww);
+ return;
+ }
+ fseek(ww->wav, 0, SEEK_SET);
+ write_header(ww, ww->data_length);
+ fclose(ww->wav);
+ free(ww);
+}
+
+void wav_write_data(void* obj, const unsigned char* data, int length) {
+ struct wav_writer* ww = (struct wav_writer*) obj;
+ if (ww->wav == NULL)
+ return;
+ fwrite(data, length, 1, ww->wav);
+ ww->data_length += length;
+}
+
diff --git a/test/wavwriter.h b/test/wavwriter.h
new file mode 100644
index 0000000..9767ad1
--- /dev/null
+++ b/test/wavwriter.h
@@ -0,0 +1,36 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2009 Martin Storsjo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#ifndef WAVWRITER_H
+#define WAVWRITER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* wav_write_open(const char *filename, int sample_rate, int bits_per_sample, int channels);
+void wav_write_close(void* obj);
+
+void wav_write_data(void* obj, const unsigned char* data, int length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+