amrwb-enc.c 3.42 KB
Newer Older
Martin Storsjo's avatar
Martin Storsjo committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/* ------------------------------------------------------------------
 * 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) {
27
	fprintf(stderr, "%s [-r bitrate] [-d] in.wav out.amr\n", name);
Martin Storsjo's avatar
Martin Storsjo committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
}

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;
48 49
	unsigned int i;
	for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
Martin Storsjo's avatar
Martin Storsjo committed
50 51 52 53 54 55 56 57 58 59 60 61 62
		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;
63
	int ch, dtx = 0;
64 65 66 67 68 69
	const char *infile, *outfile;
	FILE* out;
	void *wav, *amr;
	int format, sampleRate, channels, bitsPerSample;
	int inputSize;
	uint8_t* inputBuf;
70
	while ((ch = getopt(argc, argv, "r:d")) != -1) {
Martin Storsjo's avatar
Martin Storsjo committed
71 72 73 74
		switch (ch) {
		case 'r':
			mode = findMode(optarg);
			break;
75 76 77
		case 'd':
			dtx = 1;
			break;
Martin Storsjo's avatar
Martin Storsjo committed
78 79 80 81 82 83 84 85 86 87
		case '?':
		default:
			usage(argv[0]);
			return 1;
		}
	}
	if (argc - optind < 2) {
		usage(argv[0]);
		return 1;
	}
88 89
	infile = argv[optind];
	outfile = argv[optind + 1];
Martin Storsjo's avatar
Martin Storsjo committed
90 91


92
	wav = wav_read_open(infile);
93 94 95 96 97
	if (!wav) {
		fprintf(stderr, "Unable to open wav file %s\n", infile);
		return 1;
	}
	if (!wav_get_header(wav, &format, &channels, &sampleRate, &bitsPerSample, NULL)) {
Martin Storsjo's avatar
Martin Storsjo committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
		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);
113 114
	inputSize = channels*2*320;
	inputBuf = (uint8_t*) malloc(inputSize);
Martin Storsjo's avatar
Martin Storsjo committed
115

116
	amr = E_IF_init();
Martin Storsjo's avatar
Martin Storsjo committed
117 118 119 120 121 122 123
	out = fopen(outfile, "wb");
	if (!out) {
		perror(outfile);
		return 1;
	}

	fwrite("#!AMR-WB\n", 1, 9, out);
124 125 126 127 128 129
	while (1) {
		int read, i, n;
		short buf[320];
		uint8_t outbuf[500];

		read = wav_read_data(wav, inputBuf, inputSize);
Martin Storsjo's avatar
Martin Storsjo committed
130 131 132 133
		read /= channels;
		read /= 2;
		if (read < 320)
			break;
134
		for (i = 0; i < 320; i++) {
Martin Storsjo's avatar
Martin Storsjo committed
135 136 137
			const uint8_t* in = &inputBuf[2*channels*i];
			buf[i] = in[0] | (in[1] << 8);
		}
138
		n = E_IF_encode(amr, mode, buf, outbuf, dtx);
Martin Storsjo's avatar
Martin Storsjo committed
139 140
		fwrite(outbuf, 1, n, out);
	}
141
	free(inputBuf);
Martin Storsjo's avatar
Martin Storsjo committed
142 143
	fclose(out);
	E_IF_exit(amr);
144
	wav_read_close(wav);
Martin Storsjo's avatar
Martin Storsjo committed
145 146 147 148

	return 0;
}