Ejemplo n.º 1
0
Result SoundSourceOpus::open() {
    int error = 0;
    QByteArray qBAFilename = m_qFilename.toLocal8Bit();

    m_ptrOpusFile = op_open_file(qBAFilename.constData(), &error);
    if ( m_ptrOpusFile == NULL ) {
        qDebug() << "opus: Input does not appear to be an Opus bitstream.";
        m_lFilelength = 0;
        return ERR;
    }

    // opusfile lib all ways gives you 48000 samplerate and stereo 16 bit sample
    m_iChannels = 2;
    this->setBitrate((int)op_bitrate_instant(m_ptrOpusFile));
    this->setSampleRate(48000);
    this->setChannels(m_iChannels);


    if (m_iChannels > 2) {
        qDebug() << "opus: No support for more than 2 m_iChannels!";
        op_free(m_ptrOpusFile);
        m_lFilelength = 0;
        return ERR;
    }

    // op_pcm_total returns the total number of frames in the ogg file. The
    // frame is the channel-independent measure of samples. The total samples in
    // the file is m_iChannels * ov_pcm_total. rryan 7/2009 I verified this by
    // hand. a 30 second long 48khz mono ogg and a 48khz stereo ogg both report
    // 1440000 for op_pcm_total.
    qint64 ret = op_pcm_total(m_ptrOpusFile, -1) * 2;

    // qDebug() << m_qFilename << "chan:" << m_iChannels << "sample:" << m_iSampleRate << "LEN:" << ret;


    if (ret >= 0) {
        // We pretend that the file is stereo to the rest of the world.
        m_lFilelength = ret;
    } else { //error
        if (ret == OP_EINVAL) {
            //The file is not seekable. Not sure if any action is needed.
            qDebug() << "opus: file is not seekable " << m_qFilename;
        }
    }

    return OK;
}
Ejemplo n.º 2
0
static int
opusdec_read (DB_fileinfo_t *_info, char *bytes, int size) {
    opusdec_info_t *info = (opusdec_info_t *)_info;

    // Work round some streamer limitations and infobar issue #22
    if (info->new_track && is_playing_track(info->new_track)) {
        info->new_track = NULL;
        send_event(info->it, DB_EV_TRACKINFOCHANGED);
        info->next_update = -2;
    }

    // Don't read past the end of a sub-track
    int samples_to_read = size / sizeof(float) / _info->fmt.channels;
    int64_t endsample = deadbeef->pl_item_get_endsample (info->it);
    if (endsample > 0) {
        opus_int64 samples_left = endsample - op_pcm_tell (info->opusfile);
        if (samples_left < samples_to_read) {
            samples_to_read = (int)samples_left;
            size = samples_to_read * sizeof(float) * _info->fmt.channels;
        }
    }

    // Read until we have enough bytes to satisfy streamer, or there are none left
    int bytes_read = 0;
    int ret = OP_HOLE;

    int samples_read = 0;
    while (samples_read < samples_to_read && (ret > 0 || ret == OP_HOLE))
    {
        int nframes = samples_to_read-samples_read;
        float pcm[nframes * _info->fmt.channels];
        int new_link = -1;
        ret = op_read_float(info->opusfile, pcm, nframes * _info->fmt.channels, &new_link);

        if (ret < 0) {
        }
        else if (new_link != info->cur_bit_stream && !op_seekable (info->opusfile) && new_streaming_link(info, new_link)) {
            samples_read = samples_to_read;
            break;
        }
        else if (ret > 0) {
            for (int channel = 0; channel < _info->fmt.channels; channel++) {
                const float *pcm_channel = &pcm[info->channelmap ? info->channelmap[channel] : channel];
                float *ptr = ((float *)bytes + samples_read*_info->fmt.channels) + channel;
                for (int sample = 0; sample < ret; sample ++, pcm_channel += _info->fmt.channels) {
                    *ptr = *pcm_channel;
                    ptr += _info->fmt.channels;
                }
            }
            samples_read += ret;
        }
    }
    bytes_read = samples_read * sizeof(float) * _info->fmt.channels;
    info->currentsample += bytes_read / (sizeof (float) * _info->fmt.channels);


    int64_t startsample = deadbeef->pl_item_get_startsample (info->it);
    _info->readpos = (float)(op_pcm_tell(info->opusfile) - startsample) / _info->fmt.samplerate;
    if (info->set_bitrate && _info->readpos > info->next_update) {
        const int rate = (int)op_bitrate_instant(info->opusfile) / 1000;
        if (rate > 0) {
            deadbeef->streamer_set_bitrate(rate);
            info->next_update = info->next_update <= 0 ? info->next_update + 1 : _info->readpos + 5;
        }
    }

    return bytes_read;
}