예제 #1
0
파일: audio.c 프로젝트: 2hamed/Telegram
int initRecorder(const char *path) {
    cleanupRecorder();
    
    if (!path) {
        return 0;
    }
    
    _fileOs = fopen(path, "wb");
    if (!_fileOs) {
        return 0;
    }
    
    inopt.rate = rate;
    inopt.gain = 0;
    inopt.endianness = 0;
    inopt.copy_comments = 0;
    inopt.rawmode = 1;
    inopt.ignorelength = 1;
    inopt.samplesize = 16;
    inopt.channels = 1;
    inopt.skip = 0;
    
    comment_init(&inopt.comments, &inopt.comments_length, opus_get_version_string());
    
    if (rate > 24000) {
        coding_rate = 48000;
    } else if (rate > 16000) {
        coding_rate = 24000;
    } else if (rate > 12000) {
        coding_rate = 16000;
    } else if (rate > 8000) {
        coding_rate = 12000;
    } else {
        coding_rate = 8000;
    }
    
    if (rate != coding_rate) {
        LOGE("Invalid rate");
        return 0;
    }
    
    header.channels = 1;
    header.channel_mapping = 0;
    header.input_sample_rate = rate;
    header.gain = inopt.gain;
    header.nb_streams = 1;
    
    int result = OPUS_OK;
    _encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_AUDIO, &result);
    if (result != OPUS_OK) {
        LOGE("Error cannot create encoder: %s", opus_strerror(result));
        return 0;
    }
    
    min_bytes = max_frame_bytes = (1275 * 3 + 7) * header.nb_streams;
    _packet = malloc(max_frame_bytes);
    
    result = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate));
    if (result != OPUS_OK) {
        LOGE("Error OPUS_SET_BITRATE returned: %s", opus_strerror(result));
        return 0;
    }
    
#ifdef OPUS_SET_LSB_DEPTH
    result = opus_encoder_ctl(_encoder, OPUS_SET_LSB_DEPTH(max(8, min(24, inopt.samplesize))));
    if (result != OPUS_OK) {
        LOGE("Warning OPUS_SET_LSB_DEPTH returned: %s", opus_strerror(result));
    }
#endif
    
    opus_int32 lookahead;
    result = opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&lookahead));
    if (result != OPUS_OK) {
        LOGE("Error OPUS_GET_LOOKAHEAD returned: %s", opus_strerror(result));
        return 0;
    }
    
    inopt.skip += lookahead;
    header.preskip = (int)(inopt.skip * (48000.0 / coding_rate));
    inopt.extraout = (int)(header.preskip * (rate / 48000.0));
    
    if (ogg_stream_init(&os, rand()) == -1) {
        LOGE("Error: stream init failed");
        return 0;
    }
    
    unsigned char header_data[100];
    int packet_size = opus_header_to_packet(&header, header_data, 100);
    op.packet = header_data;
    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);
    
    while ((result = ogg_stream_flush(&os, &og))) {
        if (!result) {
            break;
        }
        
        int pageBytesWritten = writeOggPage(&og, _fileOs);
        if (pageBytesWritten != og.header_len + og.body_len) {
            LOGE("Error: failed writing header to output stream");
            return 0;
        }
        bytes_written += pageBytesWritten;
        pages_out++;
    }
    
    comment_pad(&inopt.comments, &inopt.comments_length, comment_padding);
    op.packet = (unsigned char *)inopt.comments;
    op.bytes = inopt.comments_length;
    op.b_o_s = 0;
    op.e_o_s = 0;
    op.granulepos = 0;
    op.packetno = 1;
    ogg_stream_packetin(&os, &op);
    
    while ((result = ogg_stream_flush(&os, &og))) {
        if (result == 0) {
            break;
        }
        
        int writtenPageBytes = writeOggPage(&og, _fileOs);
        if (writtenPageBytes != og.header_len + og.body_len) {
            LOGE("Error: failed writing header to output stream");
            return 0;
        }
        
        bytes_written += writtenPageBytes;
        pages_out++;
    }
    
    free(inopt.comments);
    
    return 1;
}
예제 #2
0
파일: opus.c 프로젝트: 0xheart0/vlc
static int OpenEncoder(vlc_object_t *p_this)
{
    encoder_t *enc = (encoder_t *)p_this;

    if (enc->fmt_out.i_codec != VLC_CODEC_OPUS)
        return VLC_EGENERIC;

    encoder_sys_t *sys = malloc(sizeof(*sys));
    if (!sys)
        return VLC_ENOMEM;

    int status = VLC_SUCCESS;
    sys->buffer = NULL;
    sys->enc = NULL;

    enc->pf_encode_audio = Encode;
    enc->fmt_in.i_codec = VLC_CODEC_FL32;
    enc->fmt_in.audio.i_rate = /* Only 48kHz */
    enc->fmt_out.audio.i_rate = 48000;
    enc->fmt_out.audio.i_channels = enc->fmt_in.audio.i_channels;

    OpusHeader header;

    opus_prepare_header(enc->fmt_out.audio.i_channels,
            enc->fmt_out.audio.i_rate, &header);

    /* needed for max encoded size calculation */
    sys->nb_streams = header.nb_streams;

    int err;
    sys->enc =
        opus_multistream_surround_encoder_create(enc->fmt_in.audio.i_rate,
                enc->fmt_in.audio.i_channels, header.channel_mapping,
                &header.nb_streams, &header.nb_coupled, header.stream_map,
                OPUS_APPLICATION_AUDIO, &err);

    if (err != OPUS_OK)
    {
        msg_Err(enc, "Could not create encoder: error %d", err);
        sys->enc = NULL;
        status = VLC_EGENERIC;
        goto error;
    }

    /* TODO: vbr, fec */

    if( enc->fmt_out.i_bitrate )
        opus_multistream_encoder_ctl(sys->enc, OPUS_SET_BITRATE( enc->fmt_out.i_bitrate ));

    /* Buffer for incoming audio, since opus only accepts frame sizes that are
       multiples of 2.5ms */
    enc->p_sys = sys;
    sys->buffer = malloc(OPUS_FRAME_SIZE * header.channels * sizeof(float));
    if (!sys->buffer) {
        status = VLC_ENOMEM;
        goto error;
    }

    sys->i_nb_samples = 0;

    sys->i_samples_delay = 0;
    int ret = opus_multistream_encoder_ctl(enc->p_sys->enc,
            OPUS_GET_LOOKAHEAD(&sys->i_samples_delay));
    if (ret != OPUS_OK)
        msg_Err(enc, "Unable to get number of lookahead samples: %s\n",
                opus_strerror(ret));

    header.preskip = sys->i_samples_delay;

    /* Now that we have preskip, we can write the header to extradata */
    if (opus_write_header((uint8_t **) &enc->fmt_out.p_extra,
                          &enc->fmt_out.i_extra, &header, opus_get_version_string()))
    {
        msg_Err(enc, "Failed to write header.");
        status = VLC_ENOMEM;
        goto error;
    }

    if (sys->i_samples_delay > 0)
    {
        const unsigned padding_samples = sys->i_samples_delay *
            enc->fmt_out.audio.i_channels;
        sys->padding = block_Alloc(padding_samples * sizeof(float));
        if (!sys->padding) {
            status = VLC_ENOMEM;
            goto error;
        }
        sys->padding->i_nb_samples = sys->i_samples_delay;
        float *pad_ptr = (float *) sys->padding->p_buffer;
        memset(pad_ptr, 0, padding_samples * sizeof(float));
    }
    else
    {
        sys->padding = NULL;
    }

    return status;

error:
    if (sys->enc)
        opus_multistream_encoder_destroy(sys->enc);
    free(sys->buffer);
    free(sys);
    return status;
}
예제 #3
0
void OggOpusFile::Init()
{
    inopt.skip=0;
    //In our case, its 160 samples/frame. Changing rate to anything rather than 8000Hz may require significant change in the way of handle number of samples to fix the encoder
    frame_size=frame_size/(48000/coding_rate);  
    /*OggOpus headers*/ /*FIXME: broke forcemono*/
    header.channels=chan;
    header.channel_mapping= 0;//header.channels>8?255:chan>2;  //=0 for  wav
    header.input_sample_rate=rate;
    header.gain=inopt.gain;   //=0 here

    st=opus_multistream_surround_encoder_create(coding_rate, chan, header.channel_mapping, &header.nb_streams, &header.nb_coupled,
        header.stream_map, frame_size<480/(48000/coding_rate)?OPUS_APPLICATION_RESTRICTED_LOWDELAY:OPUS_APPLICATION_AUDIO, &ret);
    if(ret!=OPUS_OK){
        fprintf(stderr, "Error cannot create encoder: %s\n", opus_strerror(ret));
        exit(1);
    }
    
    max_frame_bytes=(1275*3+7)*header.nb_streams;
    min_bytes=max_frame_bytes;
    m_outBuf = (unsigned char*)malloc(max_frame_bytes);
    if(m_outBuf==NULL){
        fprintf(stderr,"Error allocating m_outBuf buffer.\n");
        exit(1);
    }

    //We would set bitrate configurable as low as 6k
    //Or use the provided formulae to calculate a optimized bitrate
    if(bitrate<0){
    /*Lower default rate for sampling rates [8000-44100) by a factor of (rate+16k)/(64k)*/
    // bitrate=((64000*header.nb_streams+32000*header.nb_coupled)*
    //             (IMIN(48,IMAX(8,((rate<44100?rate:48000)+1000)/1000))+16)+32)>>6;
        bitrate=6000;

    }

    if(bitrate>(1024000*chan)||bitrate<500){
        fprintf(stderr,"Error: Bitrate %d bits/sec is insane.\nDid you mistake bits for kilobits?\n",bitrate);
        fprintf(stderr,"--bitrate values from 6-256 kbit/sec per channel are meaningful.\n");
        exit(1);
    }
    bitrate=IMIN(chan*256000,bitrate);

    ret=opus_multistream_encoder_ctl(st, OPUS_SET_BITRATE(bitrate));
    if(ret!=OPUS_OK){
        fprintf(stderr,"Error OPUS_SET_BITRATE returned: %s\n",opus_strerror(ret));
        exit(1);
    }

    ret=opus_multistream_encoder_ctl(st, OPUS_SET_VBR(!with_hard_cbr));
    if(ret!=OPUS_OK){
        fprintf(stderr,"Error OPUS_SET_VBR returned: %s\n",opus_strerror(ret));
        exit(1);
    }

    if(!with_hard_cbr){
        ret=opus_multistream_encoder_ctl(st, OPUS_SET_VBR_CONSTRAINT(with_cvbr));
        if(ret!=OPUS_OK){
            fprintf(stderr,"Error OPUS_SET_VBR_CONSTRAINT returned: %s\n",opus_strerror(ret));
            exit(1);
        }
    }
    ret=opus_multistream_encoder_ctl(st, OPUS_SET_COMPLEXITY(complexity));
    if(ret!=OPUS_OK){
        fprintf(stderr,"Error OPUS_SET_COMPLEXITY returned: %s\n",opus_strerror(ret));
        exit(1);
    }

    ret=opus_multistream_encoder_ctl(st, OPUS_SET_PACKET_LOSS_PERC(expect_loss));
    if(ret!=OPUS_OK){
        fprintf(stderr,"Error OPUS_SET_PACKET_LOSS_PERC returned: %s\n",opus_strerror(ret));
        exit(1);
    }

#ifdef OPUS_SET_LSB_DEPTH
    ret=opus_multistream_encoder_ctl(st, OPUS_SET_LSB_DEPTH(IMAX(8,IMIN(24,inopt.samplesize))));
    if(ret!=OPUS_OK){
        fprintf(stderr,"Warning OPUS_SET_LSB_DEPTH returned: %s\n",opus_strerror(ret));
    }
#endif

    for(i=0;i<opt_ctls;i++){
    int target=opt_ctls_ctlval[i*3];
    if(target==-1){
        ret=opus_multistream_encoder_ctl(st,opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]);
        if(ret!=OPUS_OK){
        fprintf(stderr,"Error opus_multistream_encoder_ctl(st,%d,%d) returned: %s\n",opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2],opus_strerror(ret));
        exit(1);
        }
    }else if(target<header.nb_streams){
        OpusEncoder *oe;
        opus_multistream_encoder_ctl(st,OPUS_MULTISTREAM_GET_ENCODER_STATE(target,&oe));
        ret=opus_encoder_ctl(oe, opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]);
        if(ret!=OPUS_OK){
        fprintf(stderr,"Error opus_encoder_ctl(st[%d],%d,%d) returned: %s\n",target,opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2],opus_strerror(ret));
        exit(1);
        }
    }else{
        fprintf(stderr,"Error --set-ctl-int target stream %d is higher than the maximum stream number %d.\n",target,header.nb_streams-1);
        exit(1);
    }
    }


    /*We do the lookahead check late so user CTLs can change it*/
    ret=opus_multistream_encoder_ctl(st, OPUS_GET_LOOKAHEAD(&lookahead));
    if(ret!=OPUS_OK){
    fprintf(stderr,"Error OPUS_GET_LOOKAHEAD returned: %s\n",opus_strerror(ret));
    exit(1);
    }
    inopt.skip+=lookahead;
    /*Regardless of the rate we're coding at the ogg timestamping/skip is
    always timed at 48000.*/
    header.preskip=inopt.skip*(48000./coding_rate);
    /* Extra samples that need to be read to compensate for the pre-skip */
    inopt.extraout=(int)header.preskip*(rate/48000.);

    /*Initialize Ogg stream struct*/
    if(ogg_stream_init(&os, serialno)==-1){
    fprintf(stderr,"Error: stream init failed\n");
    exit(1);
    }



    int opus_app;
    fprintf(stderr,"Encoding using 1.1");
    opus_multistream_encoder_ctl(st,OPUS_GET_APPLICATION(&opus_app));
    if(opus_app==OPUS_APPLICATION_VOIP)fprintf(stderr," (VoIP)\n");
    else if(opus_app==OPUS_APPLICATION_AUDIO)fprintf(stderr," (audio)\n");
    else if(opus_app==OPUS_APPLICATION_RESTRICTED_LOWDELAY)fprintf(stderr," (low-delay)\n");
    else fprintf(stderr," (unknown)\n");
    fprintf(stderr,"-----------------------------------------------------\n");
    fprintf(stderr,"   Input: %0.6gkHz %d channel%s\n",
            header.input_sample_rate/1000.,chan,chan<2?"":"s");
    fprintf(stderr,"  Output: %d channel%s (",header.channels,header.channels<2?"":"s");
    if(header.nb_coupled>0)fprintf(stderr,"%d coupled",header.nb_coupled*2);
    if(header.nb_streams-header.nb_coupled>0)fprintf(stderr,
       "%s%d uncoupled",header.nb_coupled>0?", ":"",
       header.nb_streams-header.nb_coupled);
    fprintf(stderr,")\n          %0.2gms packets, %0.6gkbit/sec%s\n",
       frame_size/(coding_rate/1000.), bitrate/1000.,
       with_hard_cbr?" CBR":with_cvbr?" CVBR":" VBR");
    fprintf(stderr," Preskip: %d\n",header.preskip);
  

}
예제 #4
0
krad_opus_t *krad_opus_encoder_create (int channels, int input_sample_rate, int bitrate, int application) {

	int c;

	krad_opus_t *krad_opus = calloc(1, sizeof(krad_opus_t));

	krad_opus->opus_header = calloc(1, sizeof(OpusHeader));

	krad_opus->input_sample_rate = input_sample_rate;
	krad_opus->channels = channels;
	krad_opus->bitrate = bitrate;
	krad_opus->application = application;
	krad_opus->complexity = DEFAULT_OPUS_COMPLEXITY;
	krad_opus->signal = OPUS_AUTO;
	krad_opus->frame_size = DEFAULT_OPUS_FRAME_SIZE;
	krad_opus->bandwidth = OPUS_BANDWIDTH_FULLBAND;

	krad_opus->new_frame_size = krad_opus->frame_size;
	krad_opus->new_complexity = krad_opus->complexity;
	krad_opus->new_bitrate = krad_opus->bitrate;
	krad_opus->new_signal = krad_opus->signal;
	krad_opus->new_bandwidth = krad_opus->bandwidth;
	
	for (c = 0; c < krad_opus->channels; c++) {
		krad_opus->ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE);
		krad_opus->resampled_ringbuf[c] = krad_ringbuffer_create (RINGBUFFER_SIZE);
		krad_opus->samples[c] = malloc(16 * 8192);
		krad_opus->resampled_samples[c] = malloc(16 * 8192);
		krad_opus->src_resampler[c] = src_new (KRAD_OPUS_SRC_QUALITY, 1, &krad_opus->src_error[c]);
		if (krad_opus->src_resampler[c] == NULL) {
			failfast ("Krad Opus Encoder: src resampler error: %s", src_strerror (krad_opus->src_error[c]));
		}
		
		krad_opus->src_data[c].src_ratio = 48000.0 / krad_opus->input_sample_rate;
	}

	if (krad_opus->channels < 3) {

		krad_opus->streams = 1;
		
		if (krad_opus->channels == 2) {
			krad_opus->coupled_streams = 1;
			krad_opus->mapping[0] = 0;
			krad_opus->mapping[1] = 1;			
		} else {
			krad_opus->coupled_streams = 0;		
			krad_opus->mapping[0] = 0;
		}
		
		krad_opus->opus_header->channel_mapping = 0;

	} else {
		krad_opus->opus_header->channel_mapping = 1;

		switch (krad_opus->channels) {
			case 3:
				krad_opus->streams = 2;
				krad_opus->coupled_streams = 1;
				krad_opus->mapping[0] = 0;
				krad_opus->mapping[1] = 1;
				krad_opus->mapping[2] = 2;
			case 4:
				krad_opus->streams = 2;
				krad_opus->coupled_streams = 2;
				krad_opus->mapping[0] = 0;
				krad_opus->mapping[1] = 1;
				krad_opus->mapping[2] = 2;
				krad_opus->mapping[3] = 3;				
			case 5:
				krad_opus->streams = 3;
				krad_opus->coupled_streams = 2;
				krad_opus->mapping[0] = 0;
				krad_opus->mapping[1] = 4;
				krad_opus->mapping[2] = 1;
				krad_opus->mapping[3] = 2;				
				krad_opus->mapping[4] = 3;
			case 6:
				krad_opus->streams = 4;
				krad_opus->coupled_streams = 2;
				krad_opus->mapping[0] = 0;
				krad_opus->mapping[1] = 4;
				krad_opus->mapping[2] = 1;
				krad_opus->mapping[3] = 2;				
				krad_opus->mapping[4] = 3;
				krad_opus->mapping[5] = 5;
			case 7:
				krad_opus->streams = 5;
				krad_opus->coupled_streams = 2;
				krad_opus->mapping[0] = 0;
				krad_opus->mapping[1] = 4;
				krad_opus->mapping[2] = 1;
				krad_opus->mapping[3] = 2;				
				krad_opus->mapping[4] = 3;
				krad_opus->mapping[5] = 5;
				krad_opus->mapping[6] = 6;				
			case 8:
				krad_opus->streams = 5;
				krad_opus->coupled_streams = 3;
				krad_opus->mapping[0] = 0;
				krad_opus->mapping[1] = 6;
				krad_opus->mapping[2] = 1;
				krad_opus->mapping[3] = 2;				
				krad_opus->mapping[4] = 3;
				krad_opus->mapping[5] = 4;
				krad_opus->mapping[6] = 5;
				krad_opus->mapping[7] = 7;				
		}
	}
	
	krad_opus->opus_header->channels = krad_opus->channels;
	krad_opus->opus_header->nb_streams = krad_opus->streams;
	krad_opus->opus_header->nb_coupled = krad_opus->coupled_streams;
	
	memcpy (krad_opus->opus_header->stream_map, krad_opus->mapping, 256);

	krad_opus->encoder = opus_multistream_encoder_create (48000,
														  krad_opus->channels,
														  krad_opus->streams,
														  krad_opus->coupled_streams,
														  krad_opus->mapping,
														  krad_opus->application,
														  &krad_opus->err);

	if (krad_opus->err != OPUS_OK) {
		failfast ("Krad Opus Encoder: Cannot create encoder: %s", opus_strerror (krad_opus->err));
	}
	

	opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_GET_LOOKAHEAD (&krad_opus->lookahead));
	krad_opus->opus_header->preskip = krad_opus->lookahead;

	krad_opus->opus_header->gain = 0;
	krad_opus->opus_header->input_sample_rate = 48000;
	
	if (opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BITRATE (krad_opus->bitrate)) != OPUS_OK) {
		failfast ("Krad Opus Encoder: bitrate request failed");
	}

	krad_opus->header_data_size = opus_header_to_packet (krad_opus->opus_header, krad_opus->header_data, 100);
	krad_opus->krad_codec_header.codec = OPUS;
	krad_opus->krad_codec_header.header[0] = krad_opus->header_data;
	krad_opus->krad_codec_header.header_size[0] = krad_opus->header_data_size;
	krad_opus->krad_codec_header.header_combined = krad_opus->header_data;
	krad_opus->krad_codec_header.header_combined_size = krad_opus->header_data_size;
	krad_opus->krad_codec_header.header_count = 2;

	krad_opus->krad_codec_header.header_size[1] = 
	8 + 4 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER=") + strlen (APPVERSION);
	
	krad_opus->opustags_header = calloc (1, krad_opus->krad_codec_header.header_size[1]);
	
	memcpy (krad_opus->opustags_header, "OpusTags", 8);
	
	krad_opus->opustags_header[8] = strlen (opus_get_version_string ());
	
	memcpy (krad_opus->opustags_header + 12, opus_get_version_string (), strlen (opus_get_version_string ()));

	krad_opus->opustags_header[12 + strlen (opus_get_version_string ())] = 1;

	krad_opus->opustags_header[12 + strlen (opus_get_version_string ()) + 4] = strlen ("ENCODER=") + strlen (APPVERSION);
	
	memcpy (krad_opus->opustags_header + 12 + strlen (opus_get_version_string ()) + 4 + 4, "ENCODER=", strlen ("ENCODER="));
	
	memcpy (krad_opus->opustags_header + 12 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER="),
			APPVERSION,
			strlen (APPVERSION));	
	
	krad_opus->krad_codec_header.header[1] = krad_opus->opustags_header;
	
	return krad_opus;

}
예제 #5
0
int krad_opus_encoder_read (krad_opus_t *krad_opus, unsigned char *buffer, int *nframes) {

	int ready;
	int bytes;
	int resp;
	int s, c;

	while (krad_ringbuffer_read_space (krad_opus->ringbuf[krad_opus->channels - 1]) >= 512 * 4 ) {
		   
		for (c = 0; c < krad_opus->channels; c++) {

			krad_opus->ret = krad_ringbuffer_peek (krad_opus->ringbuf[c], (char *)krad_opus->samples[c], (512 * 4) );
			
			krad_opus->src_data[c].data_in = krad_opus->samples[c];
			krad_opus->src_data[c].input_frames = 512;
			krad_opus->src_data[c].data_out = krad_opus->resampled_samples[c];
			krad_opus->src_data[c].output_frames = 2048;
			krad_opus->src_error[c] = src_process (krad_opus->src_resampler[c], &krad_opus->src_data[c]);
			if (krad_opus->src_error[c] != 0) {
				failfast ("Krad Opus Encoder: src resampler error: %s\n", src_strerror(krad_opus->src_error[c]));
			}
			krad_ringbuffer_read_advance (krad_opus->ringbuf[c], (krad_opus->src_data[c].input_frames_used * 4) );
			krad_opus->ret = krad_ringbuffer_write (krad_opus->resampled_ringbuf[c],
										   (char *)krad_opus->resampled_samples[c],
										           (krad_opus->src_data[c].output_frames_gen * 4) );
		}
	}
	
	if (krad_opus->new_bitrate != krad_opus->bitrate) {
		krad_opus->bitrate = krad_opus->new_bitrate;
		resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BITRATE(krad_opus->bitrate));
		if (resp != OPUS_OK) {
			failfast ("Krad Opus Encoder: bitrate request failed %s\n", opus_strerror (resp));
		} else {
			printk  ("Krad Opus Encoder: set opus bitrate %d\n", krad_opus->bitrate);
		}
	}
	
	if (krad_opus->new_frame_size != krad_opus->frame_size) {
		krad_opus->frame_size = krad_opus->new_frame_size;
		printk ("Krad Opus Encoder: frame size is now %d\n", krad_opus->frame_size);		
	}
	
	if (krad_opus->new_complexity != krad_opus->complexity) {
		krad_opus->complexity = krad_opus->new_complexity;
		resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_COMPLEXITY(krad_opus->complexity));
		if (resp != OPUS_OK) {
			failfast ("Krad Opus Encoder: complexity request failed %s. \n", opus_strerror(resp));
		} else {
			printk ("Krad Opus Encoder: set opus complexity %d\n", krad_opus->complexity);
		}
	}	

	if (krad_opus->new_signal != krad_opus->signal) {
		krad_opus->signal = krad_opus->new_signal;
		resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_SIGNAL(krad_opus->signal));
		if (resp != OPUS_OK) {
			failfast ("Krad Opus Encoder: signal request failed %s\n", opus_strerror(resp));
		} else {
			printk ("Krad Opus Encoder: set opus signal mode %d\n", krad_opus->signal);
		}
	}
	
	if (krad_opus->new_bandwidth != krad_opus->bandwidth) {
		krad_opus->bandwidth = krad_opus->new_bandwidth;
		resp = opus_multistream_encoder_ctl (krad_opus->encoder, OPUS_SET_BANDWIDTH(krad_opus->bandwidth));
		if (resp != OPUS_OK) {
			failfast ("Krad Opus Encoder: bandwidth request failed %s\n", opus_strerror(resp));
		} else {
			printk ("Krad Opus Encoder: Set Opus bandwidth mode %d\n", krad_opus->bandwidth);
		}
	}
		
	ready = 1;
	
	for (c = 0; c < krad_opus->channels; c++) {
		if (krad_ringbuffer_read_space (krad_opus->resampled_ringbuf[c]) < krad_opus->frame_size * 4) {
			ready = 0;
		}
	}

	if (ready == 1) {

		for (c = 0; c < krad_opus->channels; c++) {
			krad_opus->ret = krad_ringbuffer_read (krad_opus->resampled_ringbuf[c],
										  (char *)krad_opus->resampled_samples[c],
										          (krad_opus->frame_size * 4) );
		}

		for (s = 0; s < krad_opus->frame_size; s++) {
			for (c = 0; c < krad_opus->channels; c++) {
				krad_opus->interleaved_resampled_samples[s * krad_opus->channels + c] = krad_opus->resampled_samples[c][s];
			}
		}

		bytes = opus_multistream_encode_float (krad_opus->encoder,
											   krad_opus->interleaved_resampled_samples,
											   krad_opus->frame_size,
											   buffer,
											   krad_opus->frame_size * 2);

		if (bytes < 0) {
			failfast ("Krad Opus Encoding failed: %s.", opus_strerror (bytes));
		}

		*nframes = krad_opus->frame_size;

		return bytes;
	}
	
	return 0;

}
예제 #6
0
파일: encode.c 프로젝트: lmangani/baresip
int opus_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
		       struct auenc_param *param, const char *fmtp)
{
	struct auenc_state *aes;
	struct opus_param prm, conf_prm;
	opus_int32 fch, vbr;
	const struct aucodec *auc = ac;

	(void)param;

	if (!aesp || !ac || !ac->ch)
		return EINVAL;

	debug("opus: encoder fmtp (%s)\n", fmtp);

	/* Save the incoming OPUS parameters from SDP offer */
	if (str_isset(fmtp)) {
		opus_mirror_params(fmtp);
	}

	aes = *aesp;

	if (!aes) {
		const opus_int32 complex = 10;
		int opuserr;

		aes = mem_zalloc(sizeof(*aes), destructor);
		if (!aes)
			return ENOMEM;

		aes->ch = ac->ch;

		aes->enc = opus_encoder_create(ac->srate, ac->ch,
					       /* this has big impact on cpu */
					       OPUS_APPLICATION_AUDIO,
					       &opuserr);
		if (!aes->enc) {
			warning("opus: encoder create: %s\n",
				opus_strerror(opuserr));
			mem_deref(aes);
			return ENOMEM;
		}

		(void)opus_encoder_ctl(aes->enc, OPUS_SET_COMPLEXITY(complex));

		*aesp = aes;
	}

	prm.srate      = 48000;
	prm.bitrate    = OPUS_AUTO;
	prm.stereo     = 1;
	prm.cbr        = 0;
	prm.inband_fec = 0;
	prm.dtx        = 0;

	opus_decode_fmtp(&prm, fmtp);

	conf_prm.bitrate = OPUS_AUTO;
	opus_decode_fmtp(&conf_prm, auc->fmtp);

	if ((prm.bitrate == OPUS_AUTO) ||
	    ((conf_prm.bitrate != OPUS_AUTO) &&
	     (conf_prm.bitrate < prm.bitrate)))
		prm.bitrate = conf_prm.bitrate;

	fch = prm.stereo ? OPUS_AUTO : 1;
	vbr = prm.cbr ? 0 : 1;

	(void)opus_encoder_ctl(aes->enc,
			       OPUS_SET_MAX_BANDWIDTH(srate2bw(prm.srate)));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_BITRATE(prm.bitrate));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_FORCE_CHANNELS(fch));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_VBR(vbr));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_INBAND_FEC(prm.inband_fec));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_DTX(prm.dtx));


#if 0
	{
	opus_int32 bw, complex;

	(void)opus_encoder_ctl(aes->enc, OPUS_GET_MAX_BANDWIDTH(&bw));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_BITRATE(&prm.bitrate));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_FORCE_CHANNELS(&fch));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_VBR(&vbr));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_INBAND_FEC(&prm.inband_fec));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_DTX(&prm.dtx));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_COMPLEXITY(&complex));

	debug("opus: encode bw=%s bitrate=%i fch=%s "
	      "vbr=%i fec=%i dtx=%i complex=%i\n",
	      bwname(bw), prm.bitrate, chname(fch),
	      vbr, prm.inband_fec, prm.dtx, complex);
	}
#endif

	return 0;
}
예제 #7
0
파일: test_opus.c 프로젝트: opuscodec/dev
int main(int argc, char *argv[])
{
   int err;
   char *inFile, *outFile;
   FILE *fin, *fout;
   OpusEncoder *enc;
   OpusDecoder *dec;
   int args;
   int len[2];
   int frame_size, channels;
   int bitrate_bps;
   unsigned char *data[2];
   int sampling_rate;
   int use_vbr;
   int internal_sampling_rate_Hz;
   int max_payload_bytes;
   int complexity;
   int use_inbandfec;
   int use_dtx;
   int forcemono;
   int cvbr = 0;
   int packet_loss_perc;
   int count=0, count_act=0, k;
   int skip;
   int stop=0;
   int tot_read=0, tot_written=0;
   short *in, *out;
   int mode;
   double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
   int bandwidth=-1;
   const char *bandwidth_string;
   int write_samples;
   int lost, lost_prev = 1;
   int toggle = 0;
   int enc_final_range[2];

   if (argc < 7 )
   {
      print_usage( argv );
      return 1;
   }

   mode = atoi(argv[1]) + OPUS_MODE_AUTO;
   sampling_rate = atoi(argv[2]);
   channels = atoi(argv[3]);
   bitrate_bps = atoi(argv[4]);

   frame_size = sampling_rate/50;

   /* defaults: */
   use_vbr = 1;
   bandwidth=BANDWIDTH_AUTO;
   internal_sampling_rate_Hz = sampling_rate;
   max_payload_bytes = MAX_PACKET;
   complexity = 10;
   use_inbandfec = 0;
   forcemono = 0;
   use_dtx = 0;
   packet_loss_perc = 0;

   args = 5;
   while( args < argc - 2 ) {
       /* process command line options */
        if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) {
            use_vbr = 0;
            args++;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-bandwidth" ) == 0 ) {
            if (strcmp(argv[ args + 1 ], "NB")==0)
                bandwidth = BANDWIDTH_NARROWBAND;
            else if (strcmp(argv[ args + 1 ], "MB")==0)
                bandwidth = BANDWIDTH_MEDIUMBAND;
            else if (strcmp(argv[ args + 1 ], "WB")==0)
                bandwidth = BANDWIDTH_WIDEBAND;
            else if (strcmp(argv[ args + 1 ], "SWB")==0)
                bandwidth = BANDWIDTH_SUPERWIDEBAND;
            else if (strcmp(argv[ args + 1 ], "FB")==0)
                bandwidth = BANDWIDTH_FULLBAND;
            else {
                fprintf(stderr, "Unknown bandwidth %s. Supported are NB, MB, WB, SWB, FB.\n", argv[ args + 1 ]);
                return 1;
            }
            args += 2;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-framesize" ) == 0 ) {
            if (strcmp(argv[ args + 1 ], "2.5")==0)
                frame_size = sampling_rate/400;
            else if (strcmp(argv[ args + 1 ], "5")==0)
                frame_size = sampling_rate/200;
            else if (strcmp(argv[ args + 1 ], "10")==0)
                frame_size = sampling_rate/100;
            else if (strcmp(argv[ args + 1 ], "20")==0)
                frame_size = sampling_rate/50;
            else if (strcmp(argv[ args + 1 ], "40")==0)
                frame_size = sampling_rate/25;
            else if (strcmp(argv[ args + 1 ], "60")==0)
                frame_size = 3*sampling_rate/50;
            else {
                fprintf(stderr, "Unsupported frame size: %s ms. Supported are 2.5, 5, 10, 20, 40, 60.\n", argv[ args + 1 ]);
                return 1;
            }
            args += 2;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-max_payload" ) == 0 ) {
            max_payload_bytes = atoi( argv[ args + 1 ] );
            args += 2;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-complexity" ) == 0 ) {
            complexity = atoi( argv[ args + 1 ] );
            args += 2;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-inbandfec" ) == 0 ) {
            use_inbandfec = 1;
            args++;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-forcemono" ) == 0 ) {
            forcemono = 1;
            args++;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cvbr" ) == 0 ) {
            cvbr = 1;
            args++;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-dtx") == 0 ) {
            use_dtx = 1;
            args++;
        } else if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
            packet_loss_perc = atoi( argv[ args + 1 ] );
            args += 2;
        } else {
            printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
            print_usage( argv );
            return 1;
        }
   }

   if( mode < OPUS_MODE_AUTO || mode > OPUS_MODE_AUDIO) {
      fprintf (stderr, "mode must be: 0, 1 or 2\n");
      return 1;
   }

   if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET)
   {
      fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
                        MAX_PACKET);
      return 1;
   }
   if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8)
   {
      fprintf (stderr, "bytes per packet must be between 0 and %d\n",
                        max_payload_bytes);
      return 1;
   }

   inFile = argv[argc-2];
   fin = fopen(inFile, "rb");
   if (!fin)
   {
      fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
      return 1;
   }
   outFile = argv[argc-1];
   fout = fopen(outFile, "wb+");
   if (!fout)
   {
      fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
      return 1;
   }

   enc = opus_encoder_create(sampling_rate, channels);
   dec = opus_decoder_create(sampling_rate, channels);

   opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
   opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
   opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
   opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
   opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(cvbr));
   opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
   opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
   opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono));
   opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
   opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));

   skip = 5*sampling_rate/1000;
   /* When SILK resamples, add 18 samples delay */
   /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
	   skip += 18;*/

   switch(bandwidth)
   {
   case BANDWIDTH_NARROWBAND:
	   bandwidth_string = "narrowband";
	   break;
   case BANDWIDTH_MEDIUMBAND:
	   bandwidth_string = "mediumband";
	   break;
   case BANDWIDTH_WIDEBAND:
	   bandwidth_string = "wideband";
	   break;
   case BANDWIDTH_SUPERWIDEBAND:
	   bandwidth_string = "superwideband";
	   break;
   case BANDWIDTH_FULLBAND:
	   bandwidth_string = "fullband";
	   break;
   case BANDWIDTH_AUTO:
	   bandwidth_string = "auto";
	   break;
   default:
	   bandwidth_string = "unknown";
   }

   printf("Encoding %d Hz input at %.3f kb/s in %s mode with %d-sample frames.\n", sampling_rate, bitrate_bps*0.001, bandwidth_string, frame_size);

   in = (short*)malloc(frame_size*channels*sizeof(short));
   out = (short*)malloc(frame_size*channels*sizeof(short));
   data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
   if( use_inbandfec ) {
       data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
   }
   while (!stop)
   {

      err = fread(in, sizeof(short), frame_size*channels, fin);
      tot_read += err;
      if (err < frame_size*channels)
      {
          int i;
          for (i=err;i<frame_size*channels;i++)
              in[i] = 0;
      }

      len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
#if OPUS_TEST_RANGE_CODER_STATE
      enc_final_range[toggle] = opus_encoder_get_final_range( enc );
#endif
      if (len[toggle] < 0)
      {
         fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
         return 1;
      }

      lost = rand()%100 < packet_loss_perc || len[toggle]==0;
      if( count >= use_inbandfec ) {
          /* delay by one packet when using in-band FEC */
          if( use_inbandfec  ) {
              if( lost_prev ) {
                  /* attempt to decode with in-band FEC from next packet */
                  opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 1);
              } else {
                  /* regular decode */
                  opus_decode(dec, data[1-toggle], len[1-toggle], out, frame_size, 0);
              }
          } else {
              opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 0);
          }
          write_samples = frame_size-skip;
          tot_written += write_samples*channels;
          if (tot_written > tot_read)
          {
              write_samples -= (tot_written-tot_read)/channels;
              stop = 1;
          }
          fwrite(out+skip, sizeof(short), write_samples*channels, fout);
          skip = 0;
      }

#if OPUS_TEST_RANGE_CODER_STATE
      /* compare final range encoder rng values of encoder and decoder */
      if( !lost && !lost_prev && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
          fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count);
          return 0;
      }
#endif

      lost_prev = lost;

      /* count bits */
      bits += len[toggle]*8;
      if( count >= use_inbandfec ) {
          nrg = 0.0;
          for ( k = 0; k < frame_size * channels; k++ ) {
              nrg += in[ k ] * (double)in[ k ];
          }
          if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
              bits_act += len[toggle]*8;
              count_act++;
          }
	      /* Variance */
	      bits2 += len[toggle]*len[toggle]*64;
      }
      count++;
      toggle = (toggle + use_inbandfec) & 1;
   }
   fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
   fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
   fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
   /* Close any files to which intermediate results were stored */
   SILK_DEBUG_STORE_CLOSE_FILES
   silk_TimerSave("opus_timing.txt");
   opus_encoder_destroy(enc);
   opus_decoder_destroy(dec);
   free(data[0]);
   if (use_inbandfec)
	   free(data[1]);
   fclose(fin);
   fclose(fout);
   free(in);
   free(out);
   return 0;
}