Пример #1
0
int opus_enc_init(opus_enc *opus)
{
    int err;

	err = 0;
	opus->header = (OpusHeader *)calloc(1, sizeof(OpusHeader));
	opus->header_data = (unsigned char *)calloc (1, 1024);	
	opus->tags = (unsigned char *)calloc (1, 1024);
	opus->buffer = (unsigned char *)calloc (1, 4 * 4096);
    srand(time(NULL));
    ogg_stream_init(&opus->os, rand());
	opus->header->gain = 0;
	opus->header->channels = opus->channel;
	
	if ((opus->bitrate < 8000) || (opus->bitrate > 320000)) {
		opus->bitrate = DEFAULT_OPUS_BITRATE;
	}

	opus->header->input_sample_rate = 48000;
	opus->encoder = opus_encoder_create (opus->header->input_sample_rate, opus->channel, OPUS_APPLICATION_AUDIO, &err);
	opus_encoder_ctl (opus->encoder, OPUS_SET_BITRATE(opus->bitrate));
	if (opus->encoder == NULL) {
		printf("Opus Encoder creation error: %s\n", opus_strerror (err));
		return 1;
	}
	opus->last_bitrate = opus->bitrate;
	opus_encoder_ctl (opus->encoder, OPUS_GET_LOOKAHEAD (&opus->header->preskip));
	opus->header_size = opus_header_to_packet (opus->header, opus->header_data, 100);

	opus->tags_size = 
	8 + 4 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER=") + strlen (VERSION);
	
	memcpy (opus->tags, "OpusTags", 8);
	
	opus->tags[8] = strlen (opus_get_version_string ());
	
	memcpy (opus->tags + 12, opus_get_version_string (), strlen (opus_get_version_string ()));

	opus->tags[12 + strlen (opus_get_version_string ())] = 1;

	opus->tags[12 + strlen (opus_get_version_string ()) + 4] = strlen ("ENCODER=") + strlen (VERSION);
	
	memcpy (opus->tags + 12 + strlen (opus_get_version_string ()) + 4 + 4, "ENCODER=", strlen ("ENCODER="));
	
	memcpy (opus->tags + 12 + strlen (opus_get_version_string ()) + 4 + 4 + strlen ("ENCODER="),
			VERSION,
			strlen (VERSION));	

	//printf("Opus Encoder Created\n");

    return 0;
}
Пример #2
0
int init_send_audio(codec_state *cs)
{
    cs->support_send_audio = 0;

    const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
    int i = 0;
    const ALchar *device_names[20];

    if (pDeviceList) {
        printf("\nAvailable Capture Devices are:\n");

        while (*pDeviceList) {
            device_names[i] = pDeviceList;
            printf("%d) %s\n", i, device_names[i]);
            pDeviceList += strlen(pDeviceList) + 1;
            ++i;
        }
    }

    printf("enter capture device number: \n");
    char dev[2];
    fgets(dev, sizeof(dev), stdin);
    cs->audio_capture_device = alcCaptureOpenDevice(device_names[dev[0] - 48], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16,
                               AUDIO_FRAME_SIZE * 4);

    if (alcGetError(cs->audio_capture_device) != AL_NO_ERROR) {
        printf("could not start capture device! %d\n", alcGetError(cs->audio_capture_device));
        return 0;
    }

    int err = OPUS_OK;
    cs->audio_bitrate = AUDIO_BITRATE;
    cs->audio_encoder = opus_encoder_create(AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &err);
    err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate));
    err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
    err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));

    opus_encoder_init(cs->audio_encoder, AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP);

    int nfo;
    err = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_LOOKAHEAD(&nfo));
    /* printf("Encoder lookahead delay : %d\n", nfo); */
    printf("init audio encoder successful\n");

    return 1;
}
Пример #3
0
already_AddRefed<TrackMetadataBase>
OpusTrackEncoder::GetMetadata()
{
  PROFILER_LABEL("OpusTrackEncoder", "GetMetadata",
    js::ProfileEntry::Category::OTHER);
  {
    // Wait if mEncoder is not initialized.
    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
    while (!mCanceled && !mInitialized) {
      mReentrantMonitor.Wait();
    }
  }

  if (mCanceled || mEncodingComplete) {
    return nullptr;
  }

  RefPtr<OpusMetadata> meta = new OpusMetadata();

  mLookahead = 0;
  int error = opus_encoder_ctl(mEncoder, OPUS_GET_LOOKAHEAD(&mLookahead));
  if (error != OPUS_OK) {
    mLookahead = 0;
  }

  // The ogg time stamping and pre-skip is always timed at 48000.
  SerializeOpusIdHeader(mChannels, mLookahead * (kOpusSamplingRate /
                        GetOutputSampleRate()), mSamplingRate,
                        &meta->mIdHeader);

  nsCString vendor;
  vendor.AppendASCII(opus_get_version_string());

  nsTArray<nsCString> comments;
  comments.AppendElement(NS_LITERAL_CSTRING("ENCODER=Mozilla" MOZ_APP_UA_VERSION));

  SerializeOpusCommentHeader(vendor, comments,
                             &meta->mCommentHeader);

  return meta.forget();
}
Пример #4
0
Файл: opus.c Проект: MSalmo/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;

    if (opus_prepare_header(enc->fmt_out.audio.i_channels,
            enc->fmt_out.audio.i_rate,
            &header))
    {
        msg_Err(enc, "Failed to prepare header.");
        status = VLC_ENOMEM;
        goto error;
    }

    /* 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, bitrate, fec */

    /* 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))
    {
        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;
}
Пример #5
0
static result_t
encode_opus_file(char *filename,
                 struct PCMReader *pcmreader,
                 int quality,
                 unsigned original_sample_rate)
{
    const int multichannel = (pcmreader->channels > 2);
    const unsigned channel_mapping = (pcmreader->channels > 8 ? 255 :
                                      pcmreader->channels > 2);
    int stream_count;
    int coupled_stream_count;
    unsigned char stream_map[255];

    int samples[BLOCK_SIZE * pcmreader->channels];
    unsigned pcm_frames;
    result_t result = ENCODE_OK;
    FILE *output_file = NULL;
    ogg_stream_state ogg_stream;
    ogg_page ogg_page;
    OpusEncoder *opus_encoder = NULL;
    OpusMSEncoder *opus_ms_encoder = NULL;
    int error;
    opus_int16 *opus_samples = NULL;
    unsigned char opus_frame[OPUS_FRAME_LEN];
    ogg_int64_t granulepos = 0;
    ogg_int64_t packetno = 0;
    opus_int32 preskip;

    /*open output file for writing*/
    if ((output_file = fopen(filename, "w+b")) == NULL) {
        return ERR_IOERROR;
    }

    if (!multichannel) {
        if ((opus_encoder = opus_encoder_create(48000,
                                                pcmreader->channels,
                                                OPUS_APPLICATION_AUDIO,
                                                &error)) == NULL) {
            fclose(output_file);
            return ERR_ENCODER_INIT;
        }

        opus_encoder_ctl(opus_encoder, OPUS_SET_COMPLEXITY(quality));
        opus_encoder_ctl(opus_encoder, OPUS_GET_LOOKAHEAD(&preskip));
    } else {
        if ((opus_ms_encoder =
             opus_multistream_surround_encoder_create(
                 48000,
                 pcmreader->channels,
                 channel_mapping,
                 &stream_count,
                 &coupled_stream_count,
                 stream_map,
                 OPUS_APPLICATION_AUDIO,
                 &error)) == NULL) {
            fclose(output_file);
            return ERR_ENCODER_INIT;
        }

        opus_multistream_encoder_ctl(opus_ms_encoder,
                                     OPUS_SET_COMPLEXITY(quality));
        opus_multistream_encoder_ctl(opus_ms_encoder,
                                     OPUS_GET_LOOKAHEAD(&preskip));
    }


    srand((unsigned)time(NULL));
    ogg_stream_init(&ogg_stream, rand());

    /*write header and comment packets to Ogg stream*/
    {
        BitstreamRecorder *header =
            bw_open_bytes_recorder(BS_LITTLE_ENDIAN);
        BitstreamWriter *header_w =(BitstreamWriter*)header;
        BitstreamRecorder *comment =
            bw_open_bytes_recorder(BS_LITTLE_ENDIAN);
        BitstreamWriter *comment_w = (BitstreamWriter*)comment;
        int i;

        /*write header packet to Ogg stream*/
        const char opushead[] = "OpusHead";
        const char opuscomment[] = "OpusTags";
        const char *vendor_string = opus_get_version_string();
        const size_t vendor_string_len = strlen(vendor_string);
        ogg_packet packet_head;
        ogg_packet packet_tags;

        header_w->write_bytes(header_w,
                              (uint8_t*)opushead,
                              (unsigned)strlen(opushead));
        header_w->write(header_w, 8, 1);       /*version*/
        header_w->write(header_w, 8, pcmreader->channels);
        header_w->write(header_w, 16, preskip);
        header_w->write(header_w, 32, original_sample_rate);
        header_w->write(header_w, 16, 0);      /*output gain*/
        header_w->write(header_w, 8, channel_mapping);
        if (channel_mapping != 0) {
            header_w->write(header_w, 8, stream_count);
            header_w->write(header_w, 8, coupled_stream_count);
            for (i = 0; i < pcmreader->channels; i++) {
                header_w->write(header_w, 8, stream_map[i]);
            }
        }

        packet_head.packet = malloc(header->bytes_written(header));
        header->data(header, (uint8_t*)packet_head.packet);
        packet_head.bytes = header->bytes_written(header);
        packet_head.b_o_s = 1;
        packet_head.e_o_s = 0;
        packet_head.granulepos = 0;
        packet_head.packetno = packetno++;
        header->close(header);

        ogg_stream_packetin(&ogg_stream, &packet_head);

        for (i = ogg_stream_flush(&ogg_stream, &ogg_page);
             i != 0;
             i = ogg_stream_flush(&ogg_stream, &ogg_page)) {
            fwrite(ogg_page.header, 1, ogg_page.header_len, output_file);
            fwrite(ogg_page.body, 1, ogg_page.body_len, output_file);
        }

        free(packet_head.packet);

        /*write comment packet to Ogg stream*/
        comment_w->write_bytes(comment_w,
                               (uint8_t*)opuscomment,
                               (unsigned)strlen(opuscomment));
        comment_w->write(comment_w, 32, (unsigned)vendor_string_len);
        comment_w->write_bytes(comment_w,
                               (uint8_t*)vendor_string,
                               (unsigned)vendor_string_len);
        comment_w->write(comment_w, 32, 0);

        packet_tags.packet = malloc(comment->bytes_written(comment));
        comment->data(comment, (uint8_t*)packet_tags.packet);
        packet_tags.bytes = comment->bytes_written(comment);
        packet_tags.b_o_s = 0;
        packet_tags.e_o_s = 0;
        packet_tags.granulepos = 0;
        packet_tags.packetno = packetno++;
        comment->close(comment);

        ogg_stream_packetin(&ogg_stream, &packet_tags);

        for (i = ogg_stream_flush(&ogg_stream, &ogg_page);
             i != 0;
             i = ogg_stream_flush(&ogg_stream, &ogg_page)) {
            fwrite(ogg_page.header, 1, ogg_page.header_len, output_file);
            fwrite(ogg_page.body, 1, ogg_page.body_len, output_file);
        }

        free(packet_tags.packet);
    }

    opus_samples = malloc(sizeof(opus_int16) *
                          pcmreader->channels *
                          BLOCK_SIZE);

    pcm_frames = pcmreader->read(pcmreader, BLOCK_SIZE, samples);
    if (!pcm_frames && (pcmreader->status != PCM_OK)) {
        result = ERR_PCMREADER;
        goto cleanup;
    }

    /*for each non-empty FrameList from PCMReader, encode Opus frame*/
    while (pcm_frames) {
        const int short_framelist = (pcm_frames < BLOCK_SIZE);
        unsigned i;
        opus_int32 encoded_size;
        ogg_packet packet;

        granulepos += pcm_frames;

        /*pad FrameList with additional null samples if necessary*/
        memset(samples + pcm_frames * pcmreader->channels,
               0,
               sizeof(int) * (BLOCK_SIZE - pcm_frames) * pcmreader->channels);

        /*rearrange channels to Vorbis order if necessary*/
        reorder_channels(pcmreader->channel_mask, BLOCK_SIZE, samples);

        /*place samples in interleaved buffer*/
        for (i = 0; i < (pcm_frames * pcmreader->channels); i++) {
            opus_samples[i] = (opus_int16)samples[i];
        }

        /*call opus_encode on interleaved buffer to get next packet*/
        if (!multichannel) {
            encoded_size = opus_encode(opus_encoder,
                                       opus_samples,
                                       BLOCK_SIZE,
                                       opus_frame,
                                       OPUS_FRAME_LEN);
        } else {
            encoded_size = opus_multistream_encode(opus_ms_encoder,
                                                   opus_samples,
                                                   BLOCK_SIZE,
                                                   opus_frame,
                                                   OPUS_FRAME_LEN);
        }

        /*get next FrameList to encode*/
        pcm_frames = pcmreader->read(pcmreader, BLOCK_SIZE, samples);
        if (!pcm_frames && (pcmreader->status != PCM_OK)) {
            result = ERR_PCMREADER;
            goto cleanup;
        }

        /*dump Opus packet to Ogg stream*/
        /*do this *after* reading the next FrameList in order to detect
          the end of stream properly based on whether the FrameList
          has no frames*/
        packet.packet = (unsigned char *)opus_frame;
        packet.bytes = encoded_size;
        packet.b_o_s = 0;
        packet.e_o_s = (short_framelist || (pcm_frames == 0));
        packet.granulepos = granulepos;
        packet.packetno = packetno;

        ogg_stream_packetin(&ogg_stream, &packet);
        while (ogg_stream_pageout(&ogg_stream, &ogg_page)) {
            fwrite(ogg_page.header, 1, ogg_page.header_len, output_file);
            fwrite(ogg_page.body, 1, ogg_page.body_len, output_file);
        }
    }

    /*flush any remaining Ogg pages to disk*/
    while (ogg_stream_flush(&ogg_stream, &ogg_page)) {
        fwrite(ogg_page.header, 1, ogg_page.header_len, output_file);
        fwrite(ogg_page.body, 1, ogg_page.body_len, output_file);
    }

cleanup:
    fclose(output_file);
    ogg_stream_clear(&ogg_stream);
    if (!multichannel) {
        opus_encoder_destroy(opus_encoder);
    } else {
        opus_multistream_encoder_destroy(opus_ms_encoder);
    }
    free(opus_samples);
    return result;
}
Пример #6
0
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;
}
Пример #7
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);
  

}
Пример #8
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;

}
Пример #9
0
int main(int argc, char *argv[])
{
    int err;
    char *inFile, *outFile;
    FILE *fin, *fout;
    OpusCustomMode *mode=NULL;
    OpusCustomEncoder *enc;
    OpusCustomDecoder *dec;
    int len;
    opus_int32 frame_size, channels, rate;
    int bytes_per_packet;
    unsigned char data[MAX_PACKET];
    int complexity;
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
    int i;
    double rmsd = 0;
#endif
    int count = 0;
    opus_int32 skip;
    opus_int16 *in, *out;
    if (argc != 9 && argc != 8 && argc != 7)
    {
        fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> "
                 " <bytes per packet> [<complexity> [packet loss rate]] "
                 "<input> <output>\n");
        return 1;
    }

    rate = (opus_int32)atol(argv[1]);
    channels = atoi(argv[2]);
    frame_size = atoi(argv[3]);
    mode = opus_custom_mode_create(rate, frame_size, NULL);
    if (mode == NULL)
    {
        fprintf(stderr, "failed to create a mode\n");
        return 1;
    }

    bytes_per_packet = atoi(argv[4]);
    if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
    {
        fprintf (stderr, "bytes per packet must be between 0 and %d\n",
                 MAX_PACKET);
        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]);
        fclose(fin);
        return 1;
    }

    enc = opus_custom_encoder_create(mode, channels, &err);
    if (err != 0)
    {
        fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
        fclose(fin);
        fclose(fout);
        return 1;
    }
    dec = opus_custom_decoder_create(mode, channels, &err);
    if (err != 0)
    {
        fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
        fclose(fin);
        fclose(fout);
        return 1;
    }
    opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));

    if (argc>7)
    {
        complexity=atoi(argv[5]);
        opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
    }

    in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
    out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));

    while (!feof(fin))
    {
        int ret;
        err = fread(in, sizeof(short), frame_size*channels, fin);
        if (feof(fin))
            break;
        len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
        if (len <= 0)
            fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));

        /* This is for simulating bit errors */
#if 0
        int errors = 0;
        int eid = 0;
        /* This simulates random bit error */
        for (i=0; i<len*8; i++)
        {
            if (rand()%atoi(argv[8])==0)
            {
                if (i<64)
                {
                    errors++;
                    eid = i;
                }
                data[i/8] ^= 1<<(7-(i%8));
            }
        }
        if (errors == 1)
            data[eid/8] ^= 1<<(7-(eid%8));
        else if (errors%2 == 1)
            data[rand()%8] ^= 1<<rand()%8;
#endif

#if 1 /* Set to zero to use the encoder's output instead */
        /* This is to simulate packet loss */
        if (argc==9 && rand()%1000<atoi(argv[argc-3]))
            /*if (errors && (errors%2==0))*/
            ret = opus_custom_decode(dec, NULL, len, out, frame_size);
        else
            ret = opus_custom_decode(dec, data, len, out, frame_size);
        if (ret < 0)
            fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
#else
        for (i=0; i<ret*channels; i++)
            out[i] = in[i];
#endif
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
        for (i=0; i<ret*channels; i++)
        {
            rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
            /*out[i] -= in[i];*/
        }
#endif
        count++;
        fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
        skip = 0;
    }
    PRINT_MIPS(stderr);

    opus_custom_encoder_destroy(enc);
    opus_custom_decoder_destroy(dec);
    fclose(fin);
    fclose(fout);
    opus_custom_mode_destroy(mode);
    free(in);
    free(out);
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
    if (rmsd > 0)
    {
        rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
        fprintf (stderr, "Error: encoder doesn't match decoder\n");
        fprintf (stderr, "RMS mismatch is %f\n", rmsd);
        return 1;
    } else {
        fprintf (stderr, "Encoder matches decoder!!\n");
    }
#endif
    return 0;
}