예제 #1
0
int AudioFormat::bytesPerFrame() const
{
    if (!isValid())
        return 0;

    return bytesPerSample() * channels();
}
예제 #2
0
static int ao_opensl_level(dtaudio_output_t *aout) {
    aout_sys_t *sys = (aout_sys_t *) aout->ao_priv;
    dt_lock(&sys->lock);
    int level = sys->samples * bytesPerSample(aout);
    const int unit_size = sys->samples_per_buf * bytesPerSample(aout);
    SLAndroidSimpleBufferQueueState st;
    if (!sys->started)
        goto END;
    SLresult res = GetState(sys->playerBufferQueue, &st);
    if (unlikely(res != SL_RESULT_SUCCESS)) {
        goto END;
    }
    level += st.count * unit_size;
    //__android_log_print(ANDROID_LOG_DEBUG,TAG, "opensl level:%d  st.count:%d sample:%d:%d \n",level, (int)st.count, sys->samples);
    END:
    dt_unlock(&sys->lock);
    return level;
}
예제 #3
0
/*****************************************************************************
 * Play: play a sound
 *****************************************************************************/
static int Play(dtaudio_output_t *aout, uint8_t *buf, int size) {
    aout_sys_t *sys = (aout_sys_t *) aout->ao_priv;
    int ret = 0;
    //__android_log_print(ANDROID_LOG_DEBUG,TAG, "space:%d level:%d  size:%d  \n",buf_space(&sys->dbt), buf_level(&sys->dbt), size);
    if (buf_space(&sys->dbt) > size) {
        ret = buf_put(&sys->dbt, buf, size);
    }
    sys->samples += ret / bytesPerSample(aout);
    //__android_log_print(ANDROID_LOG_DEBUG,TAG, "add sampels, %d add %d \n",sys->samples, ret / bytesPerSample(aout));

    /* Fill OpenSL buffer */
    WriteBuffer(aout); // will read data in callback
    return ret;
}
예제 #4
0
static int WriteBuffer(dtaudio_output_t *aout) {
    aout_sys_t *sys = (aout_sys_t *) aout->ao_priv;
    const int unit_size = sys->samples_per_buf * bytesPerSample(aout);

    /* Check if we can fill at least one buffer unit by chaining blocks */
    if (sys->dbt.level < unit_size) {
        return false;
    }

    SLAndroidSimpleBufferQueueState st;
    SLresult res = GetState(sys->playerBufferQueue, &st);
    if (unlikely(res != SL_RESULT_SUCCESS)) {
        return false;
    }

    if (st.count == OPENSLES_BUFFERS)
        return false;

    int done = 0;
    while (done < unit_size) {
        int cur = buf_level(&sys->dbt);
        if (cur > unit_size - done)
            cur = unit_size - done;

        //memcpy(&sys->buf[unit_size * sys->next_buf + done], b->p_buffer, cur);
        buf_get(&sys->dbt, &sys->buf[unit_size * sys->next_buf + done], cur);
        done += cur;

        if (done == unit_size)
            break;
    }

    SLresult r = Enqueue(sys->playerBufferQueue,
                         &sys->buf[unit_size * sys->next_buf], unit_size);

    sys->samples -= sys->samples_per_buf;
    //__android_log_print(ANDROID_LOG_DEBUG,TAG, "minus sampels, %d minus %d \n",sys->samples, sys->samples_per_buf);

    if (r == SL_RESULT_SUCCESS) {
        if (++sys->next_buf == OPENSLES_BUFFERS)
            sys->next_buf = 0;
        return true;
    } else {
        /* XXX : if writing fails, we don't retry */
        return false;
    }
}
예제 #5
0
static int64_t ao_opensl_get_latency(dtaudio_output_t *aout) {
    int64_t latency;
    int ret = 0;
    int level = 0;
    aout_sys_t *sys = (aout_sys_t *) aout->ao_priv;

#if 1
    TimeGet(aout, &latency);
    if (latency == -1)
        return 0;
    latency = 9 * latency / 100;
#else
    dtaudio_para_t *para = &aout->para;
    level = ao_opensl_level(aout);
    int sample_num;
    float pts_ratio = 0.0;
    pts_ratio = (double) 90000 / para->dst_samplerate;
    sample_num = level / bytesPerSample(aout);
    latency += (sample_num * pts_ratio);
#endif
    //__android_log_print(ANDROID_LOG_DEBUG,TAG, "opensl latency, level:%d latency:%lld \n",level, latency);
    return latency;
}
예제 #6
0
static int Start(dtaudio_output_t *aout) {
    SLresult result;

    aout_sys_t *sys = (aout_sys_t *) aout->ao_priv;
    dtaudio_para_t *para = &aout->para;

    // configure audio source - this defines the number of samples you can enqueue.
    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
            SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
            OPENSLES_BUFFERS
    };

    int mask;

    if (para->dst_channels > 1)
        mask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    else
        mask = SL_SPEAKER_FRONT_CENTER;


    SLDataFormat_PCM format_pcm;
    format_pcm.formatType = SL_DATAFORMAT_PCM;
    format_pcm.numChannels = para->dst_channels;
    //format_pcm.samplesPerSec    = ((SLuint32) para->dst_samplerate * 1000) ;
    format_pcm.samplesPerSec = ((SLuint32) convertSampleRate(para->dst_samplerate));
    format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
    format_pcm.channelMask = mask;
    format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;

    SLDataSource audioSrc = {&loc_bufq, &format_pcm};

    // configure audio sink
    SLDataLocator_OutputMix loc_outmix = {
            SL_DATALOCATOR_OUTPUTMIX,
            sys->outputMixObject
    };
    SLDataSink audioSnk = {&loc_outmix, NULL};

    //create audio player
    const SLInterfaceID ids2[] = {sys->SL_IID_ANDROIDSIMPLEBUFFERQUEUE, sys->SL_IID_VOLUME};
    static const SLboolean req2[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc,
                               &audioSnk, sizeof(ids2) / sizeof(*ids2),
                               ids2, req2);
    if (unlikely(result != SL_RESULT_SUCCESS)) { // error
        return -1;
        /* Try again with a more sensible samplerate */
#if 0
        fmt->i_rate = 44100;
        format_pcm.samplesPerSec = ((SLuint32) 44100 * 1000) ;
        result = CreateAudioPlayer(sys->engineEngine, &sys->playerObject, &audioSrc,
                &audioSnk, sizeof(ids2) / sizeof(*ids2),
                ids2, req2);
#endif
    }
    CHECK_OPENSL_ERROR("Failed to create audio player");

    result = Realize(sys->playerObject, SL_BOOLEAN_FALSE);
    CHECK_OPENSL_ERROR("Failed to realize player object.");

    result = GetInterface(sys->playerObject, sys->SL_IID_PLAY, &sys->playerPlay);
    CHECK_OPENSL_ERROR("Failed to get player interface.");

    result = GetInterface(sys->playerObject, sys->SL_IID_VOLUME, &sys->volumeItf);
    CHECK_OPENSL_ERROR("failed to get volume interface.");

    result = GetInterface(sys->playerObject, sys->SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                          &sys->playerBufferQueue);
    CHECK_OPENSL_ERROR("Failed to get buff queue interface");

    result = RegisterCallback(sys->playerBufferQueue, PlayedCallback,
                              (void *) aout);
    CHECK_OPENSL_ERROR("Failed to register buff queue callback.");

    // set the player's state to playing
    result = SetPlayState(sys->playerPlay, SL_PLAYSTATE_PLAYING);
    CHECK_OPENSL_ERROR("Failed to switch to playing state");

    /* XXX: rounding shouldn't affect us at normal sampling rate */
    sys->rate = para->dst_samplerate;
    sys->samples_per_buf = OPENSLES_BUFLEN * para->dst_samplerate / 1000;
    sys->buf = malloc(OPENSLES_BUFFERS * sys->samples_per_buf * bytesPerSample(aout));
    if (!sys->buf)
        goto error;

    sys->started = 0;
    sys->next_buf = 0;

    sys->samples = 0;
    SetPositionUpdatePeriod(sys->playerPlay, AOUT_MIN_PREPARE_TIME * 1000 / CLOCK_FREQ);
    return 0;

    error:
    if (sys->playerObject) {
        Destroy(sys->playerObject);
        sys->playerObject = NULL;
    }

    return -1;
}
예제 #7
0
    int DecoderAudio::decodeRender()
    {
        /*
         *  Process some special Events
         * 1) BOS
         * 2) EOS
         */
        AVPacket pkt;

        av_init_packet(&pkt);
        CHECK_POINTER_INT(mQueue, -1);
        LOGD("AudioQueue get start()");

        if (mQueue -> get(&pkt, true) != PacketQueue::PQ_OP_SUCCESS)
        {
            LOGE("getAudio Packet error, thread exit!");

            return -1;
        }

        LOGD("AudioQueue get end()");

        if (&BOS_PKT == &pkt)
        {
            LOGI("Audio Decoder Received BOS PKT!");

            /* update our clock */
            pkt.pts;

            return 0;
        }
        else if (&EOS_PKT == &pkt)
        {
            LOGI("Audio Decoder Received EOS PKT!");

            return 0;
        }

        if (pkt.pts != AV_NOPTS_VALUE)
        {
            mAudioClock = av_q2d(mStream -> time_base) * pkt.pts;
        }

        LOGD("after adjust 1 mAudioClock:%f!", mAudioClock);

        AVCodecContext * dec = mStream -> codec;

        CHECK_POINTER_INT(dec, -1);

        int       remainBufSize    = mSamplesSize,
                  curOutputBufSize = mSamplesSize;
        int       dataSize         = 0;
        int16_t * outputBuf        = mSamples;
        AVPacket  dupPkt           = pkt;

        while ((dupPkt.size > 0) && ((curOutputBufSize = remainBufSize) > 0))
        {
            LOGD("Before avcodec_decode_audio3()");

            int len = avcodec_decode_audio3(mStream -> codec, (int16_t *) outputBuf, &curOutputBufSize, &pkt);

            LOGD("after avcodec_decode_audio3() len:%d, curOutputBufSize:%d", len, curOutputBufSize);

            if ((len < 0) || (!curOutputBufSize))
            {
                dupPkt.size = 0;

                break;
            }

            LOGD("After avcodec_decode_audio3()");

            dupPkt.data   += len;
            dupPkt.size   -= len;
            remainBufSize -= curOutputBufSize;
            outputBuf     += curOutputBufSize / (sizeof(int16_t));
            dataSize      += curOutputBufSize;

            LOGD("Audio Decoder Thread Processing");
        }

        LOGD("Jump out of while loop");

        double bytesPerSec = dec -> channels * bytesPerSample(dec -> sample_fmt) * dec -> sample_rate;

        mAudioClock += (double) dataSize / (double) (bytesPerSec);

        LOGD("after adjust 2 mAudioClock:%f, mLastClock:%f!", mAudioClock, mLastClock);

        // TODO:
        // update the delay time
        mTimer = (mAudioClock - mLastClock);

        // call handler for posting buffer to os audio driver
        LOGD("Before rendorHook() mTimer:%f", mTimer);
        rendorHook(mSamples, dataSize);

        long delta = now() - mLastAbsTime;

        LOGD("delta:%lld, mLastAbsTime:%lld, now():%lld", delta, mLastAbsTime, now());

        mLastAbsTime = now();

        usleep(mTimer * 1e6);

        mLastClock = mAudioClock;

        CHECK_POINTER_INT(mBuddy, -1);

        BuddyEvent evt;

        evt.type       = AV_SYNC;
        evt.data.dData = mAudioClock;

        LOGD("Ready to call mBuddy's onBuddyEvent()");
        mBuddy-> onBuddyEvent(this, evt);
        av_free_packet(&pkt);
        LOGD("Ready to call av_free_packet() called!");

        return 0;
    }
예제 #8
0
/*********************************
Fonction RecordFichier
Permet d'enregistrer un fichier WAV
*********************************/
void UAudioCaptureMic::mainLoop()
{
	if(!_sound)
	{
		UERROR("Recorder is not initialized.");
		this->kill();
		return;
	}
    FMOD_RESULT result;
    void *ptr1 = 0, *ptr2 = 0;
    int blockLength;
    unsigned int len1 = 0, len2 = 0;

    unsigned int recordPos = 0;

	result = UAudioSystem::getRecordPosition(_driver, &recordPos); UASSERT_MSG(result==FMOD_OK, FMOD_ErrorString(result));
	if (recordPos != _lastRecordPos)
	{
		blockLength = (int)recordPos - (int)_lastRecordPos;
		if (blockLength < 0)
		{
			blockLength += _soundLength;
		}

		// * exinfo.numchannels * 2 = stereo 16bit.  1 sample = 4 bytes.
		// Lock the sound to get access to the raw data.
		FMOD_Sound_Lock(_sound, _lastRecordPos * channels() * bytesPerSample(), blockLength * channels() * bytesPerSample(), &ptr1, &ptr2, &len1, &len2);
		{
			if (ptr1 && len1)    //    Write it to disk.
			{
				if(_fp)
				{
					//write to file
					_dataLength += fwrite(ptr1, 1, len1, _fp);
				}

				// push back in the frames buffer
				pushBackSamples(ptr1, len1);
			}

			if (ptr2 && len2)    //    Write it to disk.
			{
				if(_fp)
				{
					//write to file
					_dataLength += fwrite(ptr2, 1, len2, _fp);
				}

				// push back in the frames buffer
				pushBackSamples(ptr2, len2);
			}
		}
		//Unlock the sound to allow FMOD to use it again.
		FMOD_Sound_Unlock(_sound, ptr1, ptr2, len1, len2);

		_lastRecordPos = recordPos;
	}

    UAudioSystem::update();

    uSleep(10);

    // If we are recording to a file, make sure to stop 
    // when the maximum file size is reached
    if (_fp && _maxFileSize != 0 && int(_dataLength) + frameLength()*bytesPerSample() > _maxFileSize)
    {
        UWARN("Recording max memory reached (%d Mb)... stopped", _maxFileSize/1000000);
        this->kill();
    }
}
예제 #9
0
bool UAudioCaptureMic::init()
{
	this->close();
	bool ok = UAudioCapture::init();
	if(ok)
	{
		std::string::size_type loc;

		if(_fileName.size())
		{
			loc = _fileName.find( ".mp3", 0 );
			if( loc != std::string::npos )
			{
#ifdef BUILT_WITH_LAME
				_encodeToMp3 = true;
#else
				_fileName.append(".wav");
				UERROR("Cannot write to a mp3, saving to a wav instead (%s)", _fileName.c_str());
#endif
			}
			_fp = fopen(_fileName.c_str(), "wb");
		}

		FMOD_RESULT result;
		FMOD_BOOL isRecording = false;
		result = UAudioSystem::isRecording(_driver, &isRecording); UASSERT_MSG(result==FMOD_OK, FMOD_ErrorString(result));
		if(isRecording)
		{
			result = UAudioSystem::recordStop(_driver); UASSERT_MSG(result==FMOD_OK, FMOD_ErrorString(result));
		}

		_dataLength = 0;
		_soundLength = 0;
		_lastRecordPos = 0;
		FMOD_CREATESOUNDEXINFO exinfo;
		memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
		exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO);
		exinfo.numchannels      = channels();
		if(bytesPerSample() == 1)
		{
			exinfo.format           = FMOD_SOUND_FORMAT_PCM8;
		}
		else if(bytesPerSample() == 2)
		{
			exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
		}
		else if(bytesPerSample() == 3)
		{
			exinfo.format           = FMOD_SOUND_FORMAT_PCM24;
		}
		else if(bytesPerSample() == 4)
		{
			exinfo.format           = FMOD_SOUND_FORMAT_PCM32;
		}
		exinfo.defaultfrequency = (int)fs();
		exinfo.length           = exinfo.defaultfrequency * bytesPerSample() * exinfo.numchannels * 2; // 2 -> pour deux secondes

		result = UAudioSystem::createSound(0, FMOD_2D | FMOD_SOFTWARE | FMOD_OPENUSER, &exinfo, &_sound); UASSERT_MSG(result==FMOD_OK, FMOD_ErrorString(result));
		if(_fp)
		{
			int channels, bits;
			float rate;
			FMOD_Sound_GetFormat(_sound, 0, 0, &channels, &bits);
			FMOD_Sound_GetDefaults(_sound, &rate, 0, 0, 0);
			UWav::writeWavHeader(_fp, _dataLength, rate, channels, bits);        //    Write out the wav header.  La longueur sera de 0 puisqu'elle est incunnue pour l'instant.
		}

		result = FMOD_Sound_GetLength(_sound, &_soundLength, FMOD_TIMEUNIT_PCM); UASSERT_MSG(result==FMOD_OK, FMOD_ErrorString(result));
	}
	return ok;
}
예제 #10
0
int AudioFormat::bytesPerSecond() const
{
    return channels() * bytesPerSample() * sampleRate();
}