Commit c5134814 authored by Martin Storsjo's avatar Martin Storsjo

Add a test application

parent 2c0385b6
......@@ -3,3 +3,4 @@
*.la
*.pc
Makefile
amrwb-enc
......@@ -65,3 +65,11 @@ libvo_amrwbenc_la_SOURCES = \
$(ENC_SRC)/voicefac.c \
$(ENC_SRC)/wb_vad.c \
$(ENC_SRC)/weight_a.c
bin_PROGRAMS = amrwb-enc$(EXEEXT)
amrwb_enc_LDADD = libvo-amrwbenc.la
amrwb_enc_SOURCES = amrwb-enc.cpp wavreader.cpp
noinst_HEADERS = wavreader.h
/* ------------------------------------------------------------------
* 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 <enc_if.h>
#include <unistd.h>
#include <stdlib.h>
#include "wavreader.h"
void usage(const char* name) {
fprintf(stderr, "%s [-r bitrate] in.wav out.amr\n", name);
}
int findMode(const char* str) {
struct {
int mode;
int rate;
} modes[] = {
{ 0, 6600 },
{ 1, 8850 },
{ 2, 12650 },
{ 3, 14250 },
{ 4, 15850 },
{ 5, 18250 },
{ 6, 19850 },
{ 7, 23050 },
{ 8, 23850 }
};
int rate = atoi(str);
int closest = -1;
int closestdiff = 0;
for (unsigned int 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 mode = 8;
int ch;
while ((ch = getopt(argc, argv, "r:")) != -1) {
switch (ch) {
case 'r':
mode = findMode(optarg);
break;
case '?':
default:
usage(argv[0]);
return 1;
}
}
if (argc - optind < 2) {
usage(argv[0]);
return 1;
}
const char* infile = argv[optind];
const char* outfile = argv[optind + 1];
FILE* out;
WavReader wav(infile);
int format, sampleRate, channels, bitsPerSample;
if (!wav.getHeader(&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 != 16000)
fprintf(stderr, "Warning, AMR-WB uses 16000 Hz sample rate (WAV file has %d Hz)\n", sampleRate);
int inputSize = channels*2*320;
uint8_t* inputBuf = new uint8_t[inputSize];
void* amr = E_IF_init();
out = fopen(outfile, "wb");
if (!out) {
perror(outfile);
return 1;
}
fwrite("#!AMR-WB\n", 1, 9, out);
while (true) {
int read = wav.readData(inputBuf, inputSize);
read /= channels;
read /= 2;
if (read < 320)
break;
short buf[320];
for (int i = 0; i < 320; i++) {
const uint8_t* in = &inputBuf[2*channels*i];
buf[i] = in[0] | (in[1] << 8);
}
uint8_t outbuf[500];
int n = E_IF_encode(amr, mode, buf, outbuf, 0);
fwrite(outbuf, 1, n, out);
}
delete [] inputBuf;
fclose(out);
E_IF_exit(amr);
return 0;
}
......@@ -14,6 +14,7 @@ AC_CANONICAL_HOST
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
......
/* ------------------------------------------------------------------
* 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"
#define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
uint32_t WavReader::readTag() {
uint32_t tag = 0;
tag = (tag << 8) | fgetc(wav);
tag = (tag << 8) | fgetc(wav);
tag = (tag << 8) | fgetc(wav);
tag = (tag << 8) | fgetc(wav);
return tag;
}
uint32_t WavReader::readInt32() {
uint32_t value = 0;
value |= fgetc(wav) << 0;
value |= fgetc(wav) << 8;
value |= fgetc(wav) << 16;
value |= fgetc(wav) << 24;
return value;
}
uint16_t WavReader::readInt16() {
uint16_t value = 0;
value |= fgetc(wav) << 0;
value |= fgetc(wav) << 8;
return value;
}
WavReader::WavReader(const char *filename) {
dataLength = 0;
format = 0;
sampleRate = 0;
bitsPerSample = 0;
channels = 0;
byteRate = 0;
blockAlign = 0;
wav = fopen(filename, "rb");
if (wav == NULL)
return;
long dataPos = 0;
while (true) {
uint32_t tag = readTag();
if (feof(wav))
break;
uint32_t length = readInt32();
if (tag != TAG('R', 'I', 'F', 'F') || length < 4) {
fseek(wav, length, SEEK_CUR);
continue;
}
uint32_t tag2 = readTag();
length -= 4;
if (tag2 != TAG('W', 'A', 'V', 'E')) {
fseek(wav, length, SEEK_CUR);
continue;
}
// RIFF chunk found, iterate through it
while (length >= 8) {
uint32_t subtag = readTag();
if (feof(wav))
break;
uint32_t sublength = readInt32();
length -= 8;
if (length < sublength)
break;
if (subtag == TAG('f', 'm', 't', ' ')) {
if (sublength < 16) {
// Insufficient data for 'fmt '
break;
}
format = readInt16();
channels = readInt16();
sampleRate = readInt32();
byteRate = readInt32();
blockAlign = readInt16();
bitsPerSample = readInt16();
} else if (subtag == TAG('d', 'a', 't', 'a')) {
dataPos = ftell(wav);
dataLength = sublength;
fseek(wav, sublength, SEEK_CUR);
} else {
fseek(wav, sublength, SEEK_CUR);
}
length -= sublength;
}
if (length > 0) {
// Bad chunk?
fseek(wav, length, SEEK_CUR);
}
}
fseek(wav, dataPos, SEEK_SET);
}
WavReader::~WavReader() {
fclose(wav);
}
bool WavReader::getHeader(int* format, int* channels, int* sampleRate, int* bitsPerSample, unsigned int* dataLength) {
if (format)
*format = this->format;
if (channels)
*channels = this->channels;
if (sampleRate)
*sampleRate = this->sampleRate;
if (bitsPerSample)
*bitsPerSample = this->bitsPerSample;
if (dataLength)
*dataLength = this->dataLength;
return this->format && this->sampleRate;
}
int WavReader::readData(unsigned char* data, unsigned int length) {
if (wav == NULL)
return -1;
if (length > dataLength)
length = dataLength;
int n = fread(data, 1, length, wav);
dataLength -= length;
return n;
}
/* ------------------------------------------------------------------
* 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 WAVREADER_H
#define WAVREADER_H
#include <stdio.h>
#include <stdint.h>
class WavReader {
public:
WavReader(const char *filename);
~WavReader();
bool getHeader(int* format, int* channels, int* sampleRate, int* bitsPerSample, unsigned int* dataLength);
int readData(unsigned char* data, unsigned int length);
private:
uint32_t readTag();
uint32_t readInt32();
uint16_t readInt16();
FILE *wav;
uint32_t dataLength;
int format;
int sampleRate;
int bitsPerSample;
int channels;
int byteRate;
int blockAlign;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment