static void enc_process(MSFilter *f){ SpeexEncState *s=(SpeexEncState*)f->data; mblk_t *im; int nbytes; uint8_t *buf; int frame_per_packet=1; if (s->frame_size<=0) return; ms_filter_lock(f); if (s->ptime>=20) { frame_per_packet = s->ptime/20; } if (frame_per_packet<=0) frame_per_packet=1; if (frame_per_packet>7) /* 7*20 == 140 ms max */ frame_per_packet=7; nbytes=s->frame_size*2; buf=(uint8_t*)alloca(nbytes*frame_per_packet); while((im=ms_queue_get(f->inputs[0]))!=NULL){ ms_bufferizer_put(s->bufferizer,im); } while(ms_bufferizer_read(s->bufferizer,buf,nbytes*frame_per_packet)==nbytes*frame_per_packet){ mblk_t *om=allocb(nbytes*frame_per_packet,0);//too large... int k; SpeexBits bits; speex_bits_init(&bits); for (k=0;k<frame_per_packet;k++) { speex_encode_int(s->state,(int16_t*)(buf + (k*s->frame_size*2)),&bits); s->ts+=s->frame_size; } speex_bits_insert_terminator(&bits); k=speex_bits_write(&bits, (char*)om->b_wptr, nbytes*frame_per_packet); om->b_wptr+=k; mblk_set_timestamp_info(om,s->ts-s->frame_size); ms_bufferizer_fill_current_metas(s->bufferizer, om); ms_queue_put(f->outputs[0],om); speex_bits_destroy(&bits); } ms_filter_unlock(f); }
int qSpeexEncode(QSpeexCodecPtr handle, void* samples, int sampleSize) { int offset; speex_bits_reset(&handle->encBits); /** Floods the console **/ /** fprintf(stderr, "encoding bytes: \n"); **/ for(offset=0; offset<sampleSize; offset+=handle->frameSize) { short* ptr = ((short*)samples) + offset; speex_encode_int(handle->encState, ptr, &handle->encBits); } speex_bits_insert_terminator(&handle->encBits); return speex_bits_nbytes(&handle->encBits); }
int universal_speex_encode(void* handle, const void* pAudioBuffer, unsigned cbAudioSamples, int* rSamplesConsumed, void* pCodedData, unsigned cbMaxCodedData, int* pcbCodedSize, unsigned* pbSendNow) { struct speex_codec_data_encoder *mpSpeexEnc = (struct speex_codec_data_encoder *)handle; assert(handle != NULL); memcpy(&mpSpeexEnc->mpBuffer[mpSpeexEnc->mBufferLoad], pAudioBuffer, SIZE_OF_SAMPLE * cbAudioSamples); mpSpeexEnc->mBufferLoad = mpSpeexEnc->mBufferLoad+cbAudioSamples; assert(mpSpeexEnc->mBufferLoad <= mpSpeexEnc->mNumSamplesPerFrame); // Check for necessary number of samples if(mpSpeexEnc->mBufferLoad == mpSpeexEnc->mNumSamplesPerFrame) { SpeexBits bits; // Wrap our buffer to speex bits structure speex_bits_init_buffer(&bits, pCodedData, cbMaxCodedData); // Preprocess data if requested if(mpSpeexEnc->mDoPreprocess) speex_preprocess(mpSpeexEnc->mpPreprocessState, mpSpeexEnc->mpBuffer, NULL); // Encode frame and append terminator speex_encode_int(mpSpeexEnc->mpEncoderState, mpSpeexEnc->mpBuffer, &bits); speex_bits_insert_terminator(&bits); // Tell that we've produced packet *pbSendNow = TRUE; *pcbCodedSize = speex_bits_nbytes(&bits); // Reset the buffer count. mpSpeexEnc->mBufferLoad = 0; } else { *pbSendNow = FALSE; *pcbCodedSize = 0; } *rSamplesConsumed = cbAudioSamples; return RPLG_SUCCESS; }
void *os_sound_start_out_thread(void *_ca) { jcall_t *ca = (jcall_t*)_ca; char data_out[10000]; short sp_data_out_s[640]; float sp_data_out_f[640]; int timestamp = 0; int i; while (ca->enable_audio != -1) { int k; speex_bits_reset(&ca->speex_bits); for (k=0; k<ca->speex_nb_packet;k++) { int j; i=read(fd, sp_data_out_s, ca->speex_fsize * sizeof(short)); if (i>0) { for (j=0; j<ca->speex_fsize;j++) { /* convert to float */ sp_data_out_f[j] = sp_data_out_s[j]; } speex_encode(ca->speex_enc, sp_data_out_f, &ca->speex_bits); } } speex_bits_insert_terminator(&ca->speex_bits); /* convert to char */ i = speex_bits_write(&ca->speex_bits, data_out, sizeof(data_out)); rtp_session_send_with_ts(ca->rtp_session, data_out, i,timestamp); timestamp+=i; } return NULL; }
static void close_output(void) { int i; char cbits[MAX_FRAME_BYTES]; Speex_ctx *ctx = speex_ctx; int nbBytes; int ret; if (ctx == NULL) return; if (dpm.fd < 0) return; /* Write last frame */ if (speex_ctx != NULL) { if ((ctx->ogg_packetid + 1) % ctx->nframes != 0) { while ((ctx->ogg_packetid + 1) % ctx->nframes != 0) { ctx->ogg_packetid++; speex_bits_pack(&ctx->bits, 15, 5); } nbBytes = speex_bits_write(&ctx->bits, cbits, MAX_FRAME_BYTES); ctx->op.packet = (unsigned char *)cbits; ctx->op.bytes = nbBytes; ctx->op.b_o_s = 0; ctx->op.e_o_s = 1; ctx->op.granulepos = (ctx->ogg_packetid + ctx->nframes) * ctx->frame_size; ctx->op.packetno = 2 + ctx->ogg_packetid / ctx->nframes; ogg_stream_packetin(&ctx->os, &ctx->op); } for (i = ctx->input_idx; i < ctx->frame_size * ctx->channels; i++) { /* left is zero-cleaned */ ctx->input[i] = 0; } if (ctx->channels == 2) speex_encode_stereo(ctx->input, ctx->frame_size, &ctx->bits); /* Encode the frame */ speex_encode(ctx->state, ctx->input, &ctx->bits); speex_bits_insert_terminator(&ctx->bits); /* Copy the bits to an array of char that can be written */ nbBytes = speex_bits_write(&ctx->bits, cbits, MAX_FRAME_BYTES); /* Flush all the bits in the struct so we can encode a new frame */ speex_bits_reset(&ctx->bits); /* ogg packet setup */ ctx->op.packet = (unsigned char *)cbits; ctx->op.bytes = nbBytes; ctx->op.b_o_s = 0; ctx->op.e_o_s = 1; ctx->op.granulepos = (ctx->ogg_packetid + ctx->nframes) * ctx->frame_size; ctx->op.packetno = 2 + ctx->ogg_packetid / ctx->nframes; ogg_stream_packetin(&ctx->os, &ctx->op); /* Write all new pages (most likely 0 or 1) */ while (ogg_stream_pageout(&ctx->os, &ctx->og)) { ret = oe_write_page(&ctx->og, dpm.fd); if (ret != ctx->og.header_len + ctx->og.body_len) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "failed writing header to output stream"); return; } else ctx->out_bytes += ret; } ogg_stream_clear(&speex_ctx->os); speex_bits_destroy(&speex_ctx->bits); speex_encoder_destroy(speex_ctx->state); close(dpm.fd); dpm.fd = -1; free(speex_ctx->input); ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Wrote %lu/%lu bytes(%g%% compressed)", ctx->out_bytes, ctx->in_bytes, ((double)ctx->out_bytes / (double)ctx->in_bytes)) * 100.; speex_ctx->input = NULL; free(speex_ctx); speex_ctx = NULL; } return; }
static int output_data(char *buf, int32 nbytes) { char cbits[MAX_FRAME_BYTES]; Speex_ctx *ctx = speex_ctx; int nbBytes; int16 *s; int i, j; int ret; int nbytes_left; if (dpm.fd < 0) return 0; ctx->in_bytes += nbytes; /* Main encoding loop (one frame per iteration) */ nbytes_left = nbytes; s = (int16 *)buf; while (1) { ctx->ogg_packetid++; /* packing 16 bit -> float sample */ for (i = ctx->input_idx; i < ctx->frame_size * ctx->channels; i++) { /* stream is ended, and buffer is not full. wait next spooling */ if (nbytes_left < 0) { /* canceling ogg packet */ ctx->ogg_packetid--; return 0; } ctx->input[i] = *s++; nbytes_left -= 2; /* -16 bit*/ ctx->input_idx++; } /* buffer is full. encode now. */ ctx->input_idx = 0; if (ctx->channels == 2) speex_encode_stereo(ctx->input, ctx->frame_size, &ctx->bits); /* Encode the frame */ speex_encode(ctx->state, ctx->input, &ctx->bits); if ((ctx->ogg_packetid + 1) % ctx->nframes != 0) continue; speex_bits_insert_terminator(&ctx->bits); /* Copy the bits to an array of char that can be written */ nbBytes = speex_bits_write(&ctx->bits, cbits, MAX_FRAME_BYTES); /* Flush all the bits in the struct so we can encode a new frame */ speex_bits_reset(&ctx->bits); /* ogg packet setup */ ctx->op.packet = (unsigned char *)cbits; ctx->op.bytes = nbBytes; ctx->op.b_o_s = 0; ctx->op.e_o_s = 0; ctx->op.granulepos = (ctx->ogg_packetid + ctx->nframes) * ctx->frame_size; ctx->op.packetno = 2 + ctx->ogg_packetid / ctx->nframes; ogg_stream_packetin(&ctx->os, &ctx->op); /* Write all new pages (most likely 0 or 1) */ while (ogg_stream_pageout(&ctx->os, &ctx->og)) { ret = oe_write_page(&ctx->og, dpm.fd); if (ret != ctx->og.header_len + ctx->og.body_len) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "failed writing header to output stream"); return -1; } else ctx->out_bytes += ret; } } return 0; }
static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush) { gint frame_size = enc->frame_size; gint bytes = frame_size * 2 * enc->channels; GstFlowReturn ret = GST_FLOW_OK; if (flush && gst_adapter_available (enc->adapter) % bytes != 0) { guint diff = gst_adapter_available (enc->adapter) % bytes; GstBuffer *buf = gst_buffer_new_and_alloc (diff); memset (GST_BUFFER_DATA (buf), 0, diff); gst_adapter_push (enc->adapter, buf); } while (gst_adapter_available (enc->adapter) >= bytes) { gint16 *data; gint outsize, written; GstBuffer *outbuf; data = (gint16 *) gst_adapter_take (enc->adapter, bytes); enc->samples_in += frame_size; GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes); if (enc->channels == 2) { speex_encode_stereo_int (data, frame_size, &enc->bits); } speex_encode_int (enc->state, data, &enc->bits); g_free (data); enc->frameno++; enc->frameno_out++; if ((enc->frameno % enc->nframes) != 0) continue; speex_bits_insert_terminator (&enc->bits); outsize = speex_bits_nbytes (&enc->bits); ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (enc->srcpad), &outbuf); if ((GST_FLOW_OK != ret)) goto done; written = speex_bits_write (&enc->bits, (gchar *) GST_BUFFER_DATA (outbuf), outsize); g_assert (written == outsize); speex_bits_reset (&enc->bits); GST_BUFFER_TIMESTAMP (outbuf) = enc->start_ts + gst_util_uint64_scale_int ((enc->frameno_out - enc->nframes) * frame_size - enc->lookahead, GST_SECOND, enc->rate); GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (frame_size * enc->nframes, GST_SECOND, enc->rate); /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */ GST_BUFFER_OFFSET_END (outbuf) = enc->granulepos_offset + ((enc->frameno_out) * frame_size - enc->lookahead); GST_BUFFER_OFFSET (outbuf) = gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND, enc->rate); ret = gst_speex_enc_push_buffer (enc, outbuf); if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret)) goto done; } done: return ret; }
static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf) { gint frame_size = enc->frame_size; gint bytes = frame_size * 2 * enc->channels, samples; gint outsize, written, dtx_ret = 0; GstMapInfo map; guint8 *data, *data0 = NULL, *bdata; gsize bsize, size; GstBuffer *outbuf; GstFlowReturn ret = GST_FLOW_OK; if (G_LIKELY (buf)) { gst_buffer_map (buf, &map, GST_MAP_READ); bdata = map.data; bsize = map.size; if (G_UNLIKELY (bsize % bytes)) { GST_DEBUG_OBJECT (enc, "draining; adding silence samples"); size = ((bsize / bytes) + 1) * bytes; data0 = data = g_malloc0 (size); memcpy (data, bdata, bsize); gst_buffer_unmap (buf, &map); bdata = NULL; } else { data = bdata; size = bsize; } } else { GST_DEBUG_OBJECT (enc, "nothing to drain"); goto done; } samples = size / (2 * enc->channels); speex_bits_reset (&enc->bits); /* FIXME what about dropped samples if DTS enabled ?? */ while (size) { GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes); if (enc->channels == 2) { speex_encode_stereo_int ((gint16 *) data, frame_size, &enc->bits); } dtx_ret += speex_encode_int (enc->state, (gint16 *) data, &enc->bits); data += bytes; size -= bytes; } speex_bits_insert_terminator (&enc->bits); outsize = speex_bits_nbytes (&enc->bits); if (bdata) gst_buffer_unmap (buf, &map); #if 0 ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf); if ((GST_FLOW_OK != ret)) goto done; #endif outbuf = gst_buffer_new_allocate (NULL, outsize, NULL); gst_buffer_map (outbuf, &map, GST_MAP_WRITE); written = speex_bits_write (&enc->bits, (gchar *) map.data, outsize); if (G_UNLIKELY (written < outsize)) { GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize); } else if (G_UNLIKELY (written > outsize)) { GST_ERROR_OBJECT (enc, "overrun: %d > %d bytes", written, outsize); written = outsize; } gst_buffer_unmap (outbuf, &map); gst_buffer_resize (outbuf, 0, written); if (!dtx_ret) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); ret = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf, samples); done: g_free (data0); return ret; }
int main(int argc, char **argv) { int nb_samples, total_samples=0, nb_encoded; int c; int option_index = 0; char *inFile, *outFile; FILE *fin, *fout; short input[MAX_FRAME_SIZE]; spx_int32_t frame_size; int quiet=0; spx_int32_t vbr_enabled=0; spx_int32_t vbr_max=0; int abr_enabled=0; spx_int32_t vad_enabled=0; spx_int32_t dtx_enabled=0; int nbBytes; const SpeexMode *mode=NULL; int modeID = -1; void *st; SpeexBits bits; char cbits[MAX_FRAME_BYTES]; int with_skeleton = 0; struct option long_options[] = { {"wideband", no_argument, NULL, 0}, {"ultra-wideband", no_argument, NULL, 0}, {"narrowband", no_argument, NULL, 0}, {"vbr", no_argument, NULL, 0}, {"vbr-max-bitrate", required_argument, NULL, 0}, {"abr", required_argument, NULL, 0}, {"vad", no_argument, NULL, 0}, {"dtx", no_argument, NULL, 0}, {"quality", required_argument, NULL, 0}, {"bitrate", required_argument, NULL, 0}, {"nframes", required_argument, NULL, 0}, {"comp", required_argument, NULL, 0}, #ifdef USE_SPEEXDSP {"denoise", no_argument, NULL, 0}, {"agc", no_argument, NULL, 0}, #endif {"no-highpass", no_argument, NULL, 0}, {"skeleton",no_argument,NULL, 0}, {"help", no_argument, NULL, 0}, {"quiet", no_argument, NULL, 0}, {"le", no_argument, NULL, 0}, {"be", no_argument, NULL, 0}, {"8bit", no_argument, NULL, 0}, {"16bit", no_argument, NULL, 0}, {"stereo", no_argument, NULL, 0}, {"rate", required_argument, NULL, 0}, {"version", no_argument, NULL, 0}, {"version-short", no_argument, NULL, 0}, {"comment", required_argument, NULL, 0}, {"author", required_argument, NULL, 0}, {"title", required_argument, NULL, 0}, {"print-rate", no_argument, NULL, 0}, {0, 0, 0, 0} }; int print_bitrate=0; spx_int32_t rate=0; spx_int32_t size; int chan=1; int fmt=16; spx_int32_t quality=-1; float vbr_quality=-1; int lsb=1; ogg_stream_state os; ogg_stream_state so; /* ogg stream for skeleton bitstream */ ogg_page og; ogg_packet op; int bytes_written=0, ret, result; int id=-1; SpeexHeader header; int nframes=1; spx_int32_t complexity=3; const char* speex_version; char vendor_string[64]; char *comments; int comments_length; int close_in=0, close_out=0; int eos=0; spx_int32_t bitrate=0; double cumul_bits=0, enc_frames=0; char first_bytes[12]; int wave_input=0; spx_int32_t tmp; #ifdef USE_SPEEXDSP SpeexPreprocessState *preprocess = NULL; int denoise_enabled=0, agc_enabled=0; #endif int highpass_enabled=1; int output_rate=0; spx_int32_t lookahead = 0; speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); snprintf(vendor_string, sizeof(vendor_string), "Encoded with Speex %s", speex_version); comment_init(&comments, &comments_length, vendor_string); /*Process command-line options*/ while(1) { c = getopt_long (argc, argv, "nwuhvV", long_options, &option_index); if (c==-1) break; switch(c) { case 0: if (strcmp(long_options[option_index].name,"narrowband")==0) { modeID = SPEEX_MODEID_NB; } else if (strcmp(long_options[option_index].name,"wideband")==0) { modeID = SPEEX_MODEID_WB; } else if (strcmp(long_options[option_index].name,"ultra-wideband")==0) { modeID = SPEEX_MODEID_UWB; } else if (strcmp(long_options[option_index].name,"vbr")==0) { vbr_enabled=1; } else if (strcmp(long_options[option_index].name,"vbr-max-bitrate")==0) { vbr_max=atoi(optarg); if (vbr_max<1) { fprintf (stderr, "Invalid VBR max bit-rate value: %d\n", vbr_max); exit(1); } } else if (strcmp(long_options[option_index].name,"abr")==0) { abr_enabled=atoi(optarg); if (!abr_enabled) { fprintf (stderr, "Invalid ABR value: %d\n", abr_enabled); exit(1); } } else if (strcmp(long_options[option_index].name,"vad")==0) { vad_enabled=1; } else if (strcmp(long_options[option_index].name,"dtx")==0) { dtx_enabled=1; } else if (strcmp(long_options[option_index].name,"quality")==0) { quality = atoi (optarg); vbr_quality=atof(optarg); } else if (strcmp(long_options[option_index].name,"bitrate")==0) { bitrate = atoi (optarg); } else if (strcmp(long_options[option_index].name,"nframes")==0) { nframes = atoi (optarg); if (nframes<1) nframes=1; if (nframes>10) nframes=10; } else if (strcmp(long_options[option_index].name,"comp")==0) { complexity = atoi (optarg); #ifdef USE_SPEEXDSP } else if (strcmp(long_options[option_index].name,"denoise")==0) { denoise_enabled=1; } else if (strcmp(long_options[option_index].name,"agc")==0) { agc_enabled=1; #endif } else if (strcmp(long_options[option_index].name,"no-highpass")==0) { highpass_enabled=0; } else if (strcmp(long_options[option_index].name,"skeleton")==0) { with_skeleton=1; } else if (strcmp(long_options[option_index].name,"help")==0) { usage(); exit(0); } else if (strcmp(long_options[option_index].name,"quiet")==0) { quiet = 1; } else if (strcmp(long_options[option_index].name,"version")==0) { version(); exit(0); } else if (strcmp(long_options[option_index].name,"version-short")==0) { version_short(); exit(0); } else if (strcmp(long_options[option_index].name,"print-rate")==0) { output_rate=1; } else if (strcmp(long_options[option_index].name,"le")==0) { lsb=1; } else if (strcmp(long_options[option_index].name,"be")==0) { lsb=0; } else if (strcmp(long_options[option_index].name,"8bit")==0) { fmt=8; } else if (strcmp(long_options[option_index].name,"16bit")==0) { fmt=16; } else if (strcmp(long_options[option_index].name,"stereo")==0) { chan=2; } else if (strcmp(long_options[option_index].name,"rate")==0) { rate=atoi (optarg); } else if (strcmp(long_options[option_index].name,"comment")==0) { if (!strchr(optarg, '=')) { fprintf (stderr, "Invalid comment: %s\n", optarg); fprintf (stderr, "Comments must be of the form name=value\n"); exit(1); } comment_add(&comments, &comments_length, NULL, optarg); } else if (strcmp(long_options[option_index].name,"author")==0) { comment_add(&comments, &comments_length, "author=", optarg); } else if (strcmp(long_options[option_index].name,"title")==0) { comment_add(&comments, &comments_length, "title=", optarg); } break; case 'n': modeID = SPEEX_MODEID_NB; break; case 'h': usage(); exit(0); break; case 'v': version(); exit(0); break; case 'V': print_bitrate=1; break; case 'w': modeID = SPEEX_MODEID_WB; break; case 'u': modeID = SPEEX_MODEID_UWB; break; case '?': usage(); exit(1); break; } } if (argc-optind!=2) { usage(); exit(1); } inFile=argv[optind]; outFile=argv[optind+1]; /*Initialize Ogg stream struct*/ srand(time(NULL)); if (ogg_stream_init(&os, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } if (with_skeleton && ogg_stream_init(&so, rand())==-1) { fprintf(stderr,"Error: stream init failed\n"); exit(1); } if (strcmp(inFile, "-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdin), _O_BINARY); #elif defined OS2 _fsetmode(stdin,"b"); #endif fin=stdin; } else { fin = fopen(inFile, "rb"); if (!fin) { perror(inFile); exit(1); } close_in=1; } { if (fread(first_bytes, 1, 12, fin) != 12) { perror("short file"); exit(1); } if (strncmp(first_bytes,"RIFF",4)==0 || strncmp(first_bytes,"riff",4)==0) { if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1) exit(1); wave_input=1; lsb=1; /* CHECK: exists big-endian .wav ?? */ } } if (modeID==-1 && !rate) { /* By default, use narrowband/8 kHz */ modeID = SPEEX_MODEID_NB; rate=8000; } else if (modeID!=-1 && rate) { mode = speex_lib_get_mode (modeID); if (rate>48000) { fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate); exit(1); } else if (rate>25000) { if (modeID != SPEEX_MODEID_UWB) { fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try ultra-wideband instead\n", mode->modeName , rate); } } else if (rate>12500) { if (modeID != SPEEX_MODEID_WB) { fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try wideband instead\n", mode->modeName , rate); } } else if (rate>=6000) { if (modeID != SPEEX_MODEID_NB) { fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try narrowband instead\n", mode->modeName , rate); } } else { fprintf (stderr, "Error: sampling rate too low: %d Hz\n", rate); exit(1); } } else if (modeID==-1) { if (rate>48000) { fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate); exit(1); } else if (rate>25000) { modeID = SPEEX_MODEID_UWB; } else if (rate>12500) { modeID = SPEEX_MODEID_WB; } else if (rate>=6000) { modeID = SPEEX_MODEID_NB; } else { fprintf (stderr, "Error: Sampling rate too low: %d Hz\n", rate); exit(1); } } else if (!rate) { if (modeID == SPEEX_MODEID_NB) rate=8000; else if (modeID == SPEEX_MODEID_WB) rate=16000; else if (modeID == SPEEX_MODEID_UWB) rate=32000; } if (!quiet) if (rate!=8000 && rate!=16000 && rate!=32000) fprintf (stderr, "Warning: Speex is only optimized for 8, 16 and 32 kHz. It will still work at %d Hz but your mileage may vary\n", rate); if (!mode) mode = speex_lib_get_mode (modeID); speex_init_header(&header, rate, 1, mode); header.frames_per_packet=nframes; header.vbr=vbr_enabled; header.nb_channels = chan; { char *st_string="mono"; if (chan==2) st_string="stereo"; if (!quiet) fprintf (stderr, "Encoding %d Hz audio using %s mode (%s)\n", header.rate, mode->modeName, st_string); } /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", header.rate, mode->bitrate, mode->modeName);*/ /*Initialize Speex encoder*/ st = speex_encoder_init(mode); if (strcmp(outFile,"-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif fout=stdout; } else { fout = fopen(outFile, "wb"); if (!fout) { perror(outFile); exit(1); } close_out=1; } speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size); speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity); speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &rate); if (quality >= 0) { if (vbr_enabled) { if (vbr_max>0) speex_encoder_ctl(st, SPEEX_SET_VBR_MAX_BITRATE, &vbr_max); speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_quality); } else speex_encoder_ctl(st, SPEEX_SET_QUALITY, &quality); } if (bitrate) { if (quality >= 0 && vbr_enabled) fprintf (stderr, "Warning: --bitrate option is overriding --quality\n"); speex_encoder_ctl(st, SPEEX_SET_BITRATE, &bitrate); } if (vbr_enabled) { tmp=1; speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); } else if (vad_enabled) { tmp=1; speex_encoder_ctl(st, SPEEX_SET_VAD, &tmp); } if (dtx_enabled) speex_encoder_ctl(st, SPEEX_SET_DTX, &tmp); if (dtx_enabled && !(vbr_enabled || abr_enabled || vad_enabled)) { fprintf (stderr, "Warning: --dtx is useless without --vad, --vbr or --abr\n"); } else if ((vbr_enabled || abr_enabled) && (vad_enabled)) { fprintf (stderr, "Warning: --vad is already implied by --vbr or --abr\n"); } if (with_skeleton) { fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n"); } if (abr_enabled) { speex_encoder_ctl(st, SPEEX_SET_ABR, &abr_enabled); } speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &highpass_enabled); speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); #ifdef USE_SPEEXDSP if (denoise_enabled || agc_enabled) { preprocess = speex_preprocess_state_init(frame_size, rate); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DENOISE, &denoise_enabled); speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &agc_enabled); lookahead += frame_size; } #endif /* first packet should be the skeleton header. */ if (with_skeleton) { add_fishead_packet(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n"); exit(1); } else bytes_written += ret; } /*Write header*/ { int packet_size; op.packet = (unsigned char *)speex_header_to_packet(&header, &packet_size); op.bytes = packet_size; op.b_o_s = 1; op.e_o_s = 0; op.granulepos = 0; op.packetno = 0; ogg_stream_packetin(&os, &op); free(op.packet); while((result = ogg_stream_flush(&os, &og))) { if(!result) break; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } op.packet = (unsigned char *)comments; op.bytes = comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); } /* fisbone packet should be write after all bos pages */ if (with_skeleton) { add_fisbone_packet(&so, os.serialno, &header); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n"); exit(1); } else bytes_written += ret; } /* writing the rest of the speex header packets */ while((result = ogg_stream_flush(&os, &og))) { if(!result) break; ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } free(comments); /* write the skeleton eos packet */ if (with_skeleton) { add_eos_packet_to_stream(&so); if ((ret = flush_ogg_stream_to_file(&so, fout))) { fprintf (stderr,"Error: failed writing skeleton header to output stream\n"); exit(1); } else bytes_written += ret; } speex_bits_init(&bits); if (!wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } if (nb_samples==0) eos=1; total_samples += nb_samples; nb_encoded = -lookahead; /*Main encoding loop (one frame per iteration)*/ while (!eos || total_samples>nb_encoded) { id++; /*Encode current frame*/ if (chan==2) speex_encode_stereo_int(input, frame_size, &bits); #ifdef USE_SPEEXDSP if (preprocess) speex_preprocess(preprocess, input, NULL); #endif speex_encode_int(st, input, &bits); nb_encoded += frame_size; if (print_bitrate) { int tmp; char ch=13; speex_encoder_ctl(st, SPEEX_GET_BITRATE, &tmp); fputc (ch, stderr); cumul_bits += tmp; enc_frames += 1; if (!quiet) { if (vad_enabled || vbr_enabled || abr_enabled) fprintf (stderr, "Bitrate is use: %d bps (average %d bps) ", tmp, (int)(cumul_bits/enc_frames)); else fprintf (stderr, "Bitrate is use: %d bps ", tmp); if (output_rate) printf ("%d\n", tmp); } } if (wave_input) { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); } else { nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL); } if (nb_samples==0) { eos=1; } if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; total_samples += nb_samples; if ((id+1)%nframes!=0) continue; speex_bits_insert_terminator(&bits); nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); speex_bits_reset(&bits); op.packet = (unsigned char *)cbits; op.bytes = nbBytes; op.b_o_s = 0; /*Is this redundent?*/ if (eos && total_samples<=nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; op.granulepos = (id+1)*frame_size-lookahead; if (op.granulepos>total_samples) op.granulepos = total_samples; /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/ op.packetno = 2+id/nframes; ogg_stream_packetin(&os, &op); /*Write all new pages (most likely 0 or 1)*/ while (ogg_stream_pageout(&os,&og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } } if ((id+1)%nframes!=0) { while ((id+1)%nframes!=0) { id++; speex_bits_pack(&bits, 15, 5); } nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); op.packet = (unsigned char *)cbits; op.bytes = nbBytes; op.b_o_s = 0; op.e_o_s = 1; op.granulepos = (id+1)*frame_size-lookahead; if (op.granulepos>total_samples) op.granulepos = total_samples; op.packetno = 2+id/nframes; ogg_stream_packetin(&os, &op); } /*Flush all pages left to be written*/ while (ogg_stream_flush(&os, &og)) { ret = oe_write_page(&og, fout); if(ret != og.header_len + og.body_len) { fprintf (stderr,"Error: failed writing header to output stream\n"); exit(1); } else bytes_written += ret; } speex_encoder_destroy(st); speex_bits_destroy(&bits); ogg_stream_clear(&os); if (close_in) fclose(fin); if (close_out) fclose(fout); return 0; }
int SpeexEncoder::EncodeFromFile(FILE *fin) { int id = -1; int nframes = 1; int lsb = 1; int fmt = 16; spx_int32_t size; nb_samples = read_samples(fin, frame_size, fmt, chan, lsb, input, &size); if (nb_samples == 0) eos = 1; total_samples += nb_samples; nb_encoded = -lookahead; /*Main encoding loop (one frame per iteration)*/ while (!eos || total_samples > nb_encoded) { id++; /*Encode current frame*/ if (chan == 2) speex_encode_stereo_int(input, frame_size, &bits); if (preprocess) speex_preprocess(preprocess, input, NULL); speex_encode_int(st, input, &bits); nb_encoded += frame_size; nb_samples = read_samples(fin, frame_size, fmt, chan, lsb, input, NULL); if (nb_samples == 0) { eos = 1; } if (eos && total_samples <= nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; total_samples += nb_samples; if ((id + 1) % nframes != 0) continue; speex_bits_insert_terminator(&bits); nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); speex_bits_reset(&bits); op.packet = (unsigned char *)cbits; op.bytes = nbBytes; op.b_o_s = 0; /*Is this redundent?*/ if (eos && total_samples <= nb_encoded) op.e_o_s = 1; else op.e_o_s = 0; op.granulepos = (id + 1)*frame_size - lookahead; if (op.granulepos > total_samples) op.granulepos = total_samples; //printf("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, 2 + id / nframes, lookahead, 5, 6); op.packetno = 2 + id / nframes; ogg_stream_packetin(&os, &op); /*Write all new pages (most likely 0 or 1)*/ while (ogg_stream_pageout(&os, &og)) { ret = oe_write_page(&og, fout); if (ret != og.header_len + og.body_len) { fprintf(stderr, "Error: failed writing header to output stream\n"); fclose(fin); exit(1); } else bytes_written += ret; } } if ((id + 1) % nframes != 0) { while ((id + 1) % nframes != 0) { id++; speex_bits_pack(&bits, 15, 5); } nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); op.packet = (unsigned char *)cbits; op.bytes = nbBytes; op.b_o_s = 0; op.e_o_s = 1; op.granulepos = (id + 1)*frame_size - lookahead; if (op.granulepos > total_samples) op.granulepos = total_samples; op.packetno = 2 + id / nframes; ogg_stream_packetin(&os, &op); } /*Flush all pages left to be written*/ while (ogg_stream_flush(&os, &og)) { ret = oe_write_page(&og, fout); if (ret != og.header_len + og.body_len) { fprintf(stderr, "Error: failed writing header to output stream\n"); fclose(fin); exit(1); } else bytes_written += ret; } int durationInSec = frame_size *id / rate; fprintf(stderr, "Duration: %d\n", durationInSec); int minutes = (int)(frame_size *id / rate)/60; int seconds = (frame_size *id / rate) - (minutes * 60); fprintf(stderr, "Duration Minutes: %d\n", minutes); fprintf(stderr, "Duration Seconds: %d\n", seconds); char duration[5]; sprintf(duration, "%05d", durationInSec); fseek(fout, durationIndex, SEEK_SET); fputs(duration, fout); fclose(fin); return 0; }
static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf) { gint frame_size = enc->frame_size; gint bytes = frame_size * 2 * enc->channels, samples, size; gint outsize, written, dtx_ret = 0; guint8 *data; GstBuffer *outbuf; GstFlowReturn ret = GST_FLOW_OK; if (G_LIKELY (buf)) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); if (G_UNLIKELY (size % bytes)) { GST_DEBUG_OBJECT (enc, "draining; adding silence samples"); size = ((size / bytes) + 1) * bytes; data = g_malloc0 (size); memcpy (data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); } } else { GST_DEBUG_OBJECT (enc, "nothing to drain"); goto done; } samples = size / (2 * enc->channels); speex_bits_reset (&enc->bits); /* FIXME what about dropped samples if DTS enabled ?? */ while (size) { GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes); if (enc->channels == 2) { speex_encode_stereo_int ((gint16 *) data, frame_size, &enc->bits); } dtx_ret += speex_encode_int (enc->state, (gint16 *) data, &enc->bits); data += bytes; size -= bytes; } speex_bits_insert_terminator (&enc->bits); outsize = speex_bits_nbytes (&enc->bits); ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf); if ((GST_FLOW_OK != ret)) goto done; written = speex_bits_write (&enc->bits, (gchar *) GST_BUFFER_DATA (outbuf), outsize); if (G_UNLIKELY (written < outsize)) { GST_ERROR_OBJECT (enc, "short write: %d < %d bytes", written, outsize); GST_BUFFER_SIZE (outbuf) = written; } else if (G_UNLIKELY (written > outsize)) { GST_ERROR_OBJECT (enc, "overrun: %d > %d bytes", written, outsize); } if (!dtx_ret) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); ret = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf, samples); done: return ret; }