/* * Open codec. */ static pj_status_t amr_codec_open( pjmedia_codec *codec, pjmedia_codec_param *attr ) { struct amr_data *amr_data = (struct amr_data*) codec->codec_data; pjmedia_codec_amr_pack_setting *setting; unsigned i; pj_uint8_t octet_align = 0; pj_int8_t enc_mode; const pj_str_t STR_FMTP_OCTET_ALIGN = {"octet-align", 11}; unsigned idx; PJ_ASSERT_RETURN(codec && attr, PJ_EINVAL); PJ_ASSERT_RETURN(amr_data != NULL, PJ_EINVALIDOP); idx = (attr->info.clock_rate <= 8000? IDX_AMR_NB: IDX_AMR_WB); enc_mode = pjmedia_codec_amr_get_mode(attr->info.avg_bps); pj_assert(enc_mode >= 0 && enc_mode < amr_bitrates_size[idx]); /* Check octet-align */ for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) { if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_FMTP_OCTET_ALIGN) == 0) { octet_align = (pj_uint8_t) (pj_strtoul(&attr->setting.dec_fmtp.param[i].val)); break; } } /* Check mode-set */ for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) { const pj_str_t STR_FMTP_MODE_SET = {"mode-set", 8}; if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_FMTP_MODE_SET) == 0) { const char *p; pj_size_t l; pj_int8_t diff = 99; /* Encoding mode is chosen based on local default mode setting: * - if local default mode is included in the mode-set, use it * - otherwise, find the closest mode to local default mode; * if there are two closest modes, prefer to use the higher * one, e.g: local default mode is 4, the mode-set param * contains '2,3,5,6', then 5 will be chosen. */ p = pj_strbuf(&attr->setting.enc_fmtp.param[i].val); l = pj_strlen(&attr->setting.enc_fmtp.param[i].val); while (l--) { if (*p>='0' && *p<=('0'+amr_bitrates_size[idx]-1)) { pj_int8_t tmp = *p - '0' - enc_mode; if (PJ_ABS(diff) > PJ_ABS(tmp) || (PJ_ABS(diff) == PJ_ABS(tmp) && tmp > diff)) { diff = tmp; if (diff == 0) break; } } ++p; } PJ_ASSERT_RETURN(diff != 99, PJMEDIA_CODEC_EFAILED); enc_mode = enc_mode + diff; break; } } amr_data->clock_rate = attr->info.clock_rate; amr_data->vad_enabled = (attr->setting.vad != 0); amr_data->plc_enabled = (attr->setting.plc != 0); amr_data->enc_mode = enc_mode; if (idx == IDX_AMR_NB) { #ifdef USE_AMRNB amr_data->encoder = Encoder_Interface_init(amr_data->vad_enabled); #endif } else { #ifdef USE_AMRWB amr_data->encoder = E_IF_init(); #endif } if (amr_data->encoder == NULL) { TRACE_((THIS_FILE, "Encoder initialization failed")); amr_codec_close(codec); return PJMEDIA_CODEC_EFAILED; } setting = &amr_data->enc_setting; pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting)); setting->amr_nb = (idx == IDX_AMR_NB? 1: 0); setting->reorder = 0; setting->octet_aligned = octet_align; setting->cmr = 15; if (idx == IDX_AMR_NB) { #ifdef USE_AMRNB amr_data->decoder = Decoder_Interface_init(); #endif } else { #ifdef USE_AMRWB amr_data->decoder = D_IF_init(); #endif } if (amr_data->decoder == NULL) { TRACE_((THIS_FILE, "Decoder initialization failed")); amr_codec_close(codec); return PJMEDIA_CODEC_EFAILED; } setting = &amr_data->dec_setting; pj_bzero(setting, sizeof(pjmedia_codec_amr_pack_setting)); setting->amr_nb = (idx == IDX_AMR_NB? 1: 0); setting->reorder = 0; setting->octet_aligned = octet_align; TRACE_((THIS_FILE, "AMR codec allocated: clockrate=%d vad=%d, plc=%d," " bitrate=%d", amr_data->clock_rate, amr_data->vad_enabled, amr_data->plc_enabled, amr_bitrates[idx][amr_data->enc_mode])); return PJ_SUCCESS; }
int encoder_write(unsigned long id, void* rbuffer, unsigned long bsize) { short lspeech[160]; unsigned int i = 0, j, z, byte_counter, k; if(pestreams[id].firstwrite) { if(pestreams[id].firstwrite == -1) return 0; if(pestreams[id].cfrequency != 8000 || pestreams[id].cchannels != 1) { MessageBox(0, uni("Sorry, input file needs to be in following format:\n8000Hz, Mono.\n\nPlease use \"Sound File Encoder\" to convert between formats (example: convert your file(s) into Wave format (with above settings), then convert those (.wav) file(s) into AMR)."), uni("AMR Conversion"), MB_ICONEXCLAMATION); pestreams[id].firstwrite = -1; return 0; } pestreams[id].fhandle = sys_file_createforcestream(pestreams[id].filepath, v_sys_file_forwrite); if(pestreams[id].fhandle == v_error_sys_file_create)return 0; memset(pestreams[id].serial_data, 0, sizeof(pestreams[id].serial_data)); pestreams[id].req_mode = MR122; pestreams[id].dtx = 0; pestreams[id].c = 0; pestreams[id].enstate = Encoder_Interface_init(pestreams[id].dtx); sys_file_write(pestreams[id].fhandle, AMR_MAGIC_NUMBER, strlen(AMR_MAGIC_NUMBER)); pestreams[id].firstwrite = 0; } j = pestreams[id].c; for(;;) { z = min(bsize - i, sizeof(pestreams[id].speech)); memcpy(((char*)pestreams[id].speech) + j, ((char*)rbuffer) + i, z - j); pestreams[id].c = z - j; if(pestreams[id].c == sizeof(pestreams[id].speech)) { for(k=0; k<160; k++) lspeech[k] = (short)(pestreams[id].speech[k] * 32767.0); byte_counter = Encoder_Interface_Encode(pestreams[id].enstate, pestreams[id].req_mode, lspeech, pestreams[id].serial_data, 0); sys_file_write(pestreams[id].fhandle, pestreams[id].serial_data, byte_counter); } i += z - j; j = 0; if(i >= bsize)break; } return 1; }
static void enc_preprocess(MSFilter *f) { EncState *s = (EncState*) f->data; s->enc = Encoder_Interface_init(s->dtx); }
static void enc_preprocess(AmrEncState *s) { s->amr_enc = Encoder_Interface_init(s->dtx); }
/* * main * * * Function: * Speech encoder main program * * Usage: encoder speech_file bitstream_file mode dtx mode_file * * Format for speech_file: * Speech is read from a binary file of 16 bits data. * * Format for ETSI bitstream file: * 1 word (2-byte) for the TX frame type * 244 words (2-byte) containing 244 bits. * Bit 0 = 0x0000 and Bit 1 = 0x0001 * 1 word (2-byte) for the mode indication * 4 words for future use, currently written as zero * * Format for 3GPP bitstream file: * Holds mode information and bits packed to octets. * Size is from 1 byte to 31 bytes. * * ETSI bitstream file format is defined using ETSI as preprocessor * definition * * mode : MR475, MR515, MR59, MR67, MR74, MR795, MR102, MR122 * mode_file : reads mode information from a file * Returns: * 0 */ int main (int argc, char * argv[]){ /* file strucrures */ FILE * file_speech = NULL; FILE * file_encoded = NULL; FILE * file_mode = NULL; /* input speech vector */ short speech[160]; /* counters */ int byte_counter, frames = 0, bytes = 0; /* pointer to encoder state structure */ int *enstate; /* requested mode */ enum Mode req_mode = MR122; int dtx = 0; /* temporary variables */ char mode_string[9]; long mode_tmp; /* bitstream filetype */ #ifndef ETSI unsigned char serial_data[32]; #else short serial_data[250] = {0}; #endif /* Process command line options */ if ((argc == 5) || (argc == 4)){ file_encoded = fopen(argv[argc - 1], "wb"); if (file_encoded == NULL){ Usage(argv); return 1; } file_speech = fopen(argv[argc - 2], "rb"); if (file_speech == NULL){ fclose(file_encoded); Usage(argv); return 1; } if (strncmp(argv[argc - 3], "-modefile=", 10) == 0){ file_mode = fopen(&argv[argc - 3][10], "rt"); if (file_mode == NULL){ Usage(argv); fclose(file_speech); fclose(file_encoded); return 1; } } else { mode_tmp = strtol(&argv[argc - 3][2], NULL, 0); for (req_mode = 0; req_mode < 8; req_mode++){ if (mode_tmp == modeConv[req_mode]) break; } if (req_mode == 8){ Usage(argv); fclose(file_speech); fclose(file_encoded); if (file_mode != NULL) fclose(file_mode); return 1; } } if (argc == 5){ if ((strcmp(argv[1], "-dtx") != 0)){ Usage(argv); fclose(file_speech); fclose(file_encoded); if (file_mode != NULL){ fclose(file_mode); } return 1; } else { dtx = 1; } } } else { Usage(argv); return 1; } enstate = Encoder_Interface_init(dtx); Copyright(); #ifndef VAD2 fprintf( stderr, "%s\n", "Code compiled with VAD option: VAD1"); #else fprintf( stderr, "%s\n", "Code compiled with VAD option: VAD2"); #endif #ifndef ETSI #ifndef IF2 /* write magic number to indicate single channel AMR file storage format */ bytes = fwrite(AMR_MAGIC_NUMBER, sizeof(char), strlen(AMR_MAGIC_NUMBER), file_encoded); #endif #endif /* read file */ while (fread( speech, sizeof (Word16), 160, file_speech ) > 0) { /* read mode */ if (file_mode != NULL){ req_mode = 8; if (fscanf(file_mode, "%9s\n", mode_string) != EOF) { mode_tmp = strtol(&mode_string[2], NULL, 0); for (req_mode = 0; req_mode < 8; req_mode++){ if (mode_tmp == modeConv[req_mode]){ break; } } } if (req_mode == 8){ break; } } frames ++; /* call encoder */ byte_counter = Encoder_Interface_Encode(enstate, req_mode, speech, serial_data, 0); bytes += byte_counter; fwrite(serial_data, sizeof (UWord8), byte_counter, file_encoded ); fflush(file_encoded); } Encoder_Interface_exit(enstate); #ifndef ETSI #ifdef IF2 fprintf ( stderr, "\n%s%i%s%i%s\n", "Frame structure AMR IF2: ", frames, " frames, ", bytes, " bytes."); #else fprintf ( stderr, "\n%s%i%s%i%s\n", "Frame structure AMR MIME file storage format: ", frames, " frames, ", bytes, " bytes."); #endif #else fprintf ( stderr, "\n%s%i%s\n", "Frame structure AMR ETSI: ", frames, " frames. "); #endif fclose(file_speech); fclose(file_encoded); if (file_mode != NULL) fclose(file_mode); 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; }
static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { #ifdef AMR_PASSTHROUGH codec->flags |= SWITCH_CODEC_FLAG_PASSTHROUGH; if (codec->fmtp_in) { codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in); } return SWITCH_STATUS_SUCCESS; #else struct amr_context *context = NULL; switch_codec_fmtp_t codec_fmtp; amr_codec_settings_t amr_codec_settings; int encoding, decoding; int x, i, argc; char *argv[10]; char fmtptmp[128]; encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE); if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(struct amr_context))))) { return SWITCH_STATUS_FALSE; } else { memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp)); codec_fmtp.private_info = &amr_codec_settings; switch_amr_fmtp_parse(codec->fmtp_in, &codec_fmtp); if (context->enc_modes) { for (i = 7; i > -1; i++) { if (context->enc_modes & (1 << i)) { context->enc_mode = (switch_byte_t) i; break; } } } if (!context->enc_mode) { context->enc_mode = globals.default_bitrate; } switch_snprintf(fmtptmp, sizeof(fmtptmp), "octet-align=%d; mode-set=%d", switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, context->enc_mode); codec->fmtp_out = switch_core_strdup(codec->memory_pool, fmtptmp); context->enc_mode = AMR_DEFAULT_BITRATE; context->encoder_state = NULL; context->decoder_state = NULL; if (encoding) { context->encoder_state = Encoder_Interface_init(context->dtx_mode); } if (decoding) { context->decoder_state = Decoder_Interface_init(); } codec->private_info = context; return SWITCH_STATUS_SUCCESS; } #endif }
int main(int argc, char *argv[]) { 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]; 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); 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; }