#import "wav_amr.h" #include #include #include #include #include "interf_enc.h" #include "interf_dec.h" #include "wavreader.h" #include "wavwriter.h" const int sizes[] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 6, 5, 5, 0, 0, 0, 0 }; int decode_amr(const char* infile, NSMutableData *outData) { FILE* in = fopen(infile, "rb"); if (!in) { return 1; } char header[6]; ssize_t n = fread(header, 1, 6, in); if (n != 6 || memcmp(header, "#!AMR\n", 6)) { fprintf(stderr, "Bad header\n"); return 1; } NSMutableData *body = [[NSMutableData alloc] init]; void* wav = wav_write_open(outData, body, 8000, 16, 1); void* amr = Decoder_Interface_init(); while (1) { uint8_t buffer[500]; /* 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) continue; 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++ = (outbuffer[i] >> 0) & 0xff; *ptr++ = (outbuffer[i] >> 8) & 0xff; } wav_write_data(wav, littleendian, 320); } fclose(in); Decoder_Interface_exit(amr); wav_write_close(wav); [outData appendData:body]; return 0; } int encode_amr(const char* infile, const char* outfile) { enum Mode mode = MR122; FILE *out; void *wav, *amr; int format, sampleRate, channels, bitsPerSample; int inputSize; uint8_t* inputBuf; 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(0); out = fopen(outfile, "wb"); if (!out) { perror(outfile); return 1; } fwrite("#!AMR\n", 1, 6, out); while (1) { short buf[160]; uint8_t outbuf[500]; 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, mode, buf, outbuf, 0); fwrite(outbuf, 1, n, out); } free(inputBuf); fclose(out); Encoder_Interface_exit(amr); wav_read_close(wav); return 0; }