diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.alt | 23 | ||||
-rw-r--r-- | test/Makefile.am | 32 | ||||
-rw-r--r-- | test/amrnb-dec.c (renamed from test/amrnb-dec.cpp) | 44 | ||||
-rw-r--r-- | test/amrnb-enc-sine.c | 59 | ||||
-rw-r--r-- | test/amrnb-enc.c | 121 | ||||
-rw-r--r-- | test/amrwb-dec.c (renamed from test/amrwb-dec.cpp) | 46 | ||||
-rw-r--r-- | test/linkboth.c | 8 | ||||
-rw-r--r-- | test/wav.cpp | 87 | ||||
-rw-r--r-- | test/wavreader.c | 162 | ||||
-rw-r--r-- | test/wavreader.h (renamed from test/wav.h) | 34 | ||||
-rw-r--r-- | test/wavwriter.c | 111 | ||||
-rw-r--r-- | test/wavwriter.h | 36 |
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 + |