/**
 * \brief start output
 * \param audec pointer to audec
 * \return 0 on success otherwise negative error code
 *
 * Call android_start(), then the callback will start being called.
 */
extern "C" int android_start(struct aml_audio_dec* audec)
{
    adec_print("android out start");

    status_t status;
    audio_out_operations_t *out_ops = &audec->aout_ops;
    AudioTrack *track = (AudioTrack *)out_ops->private_data;

    Mutex::Autolock _l(mLock);

    if (!track) {
        adec_print("No track instance!\n");
        return -1;
    }

    status = track->initCheck();
    if (status != NO_ERROR) {
        delete track;
        out_ops->private_data = NULL;
        return -1;
    }

    track->start();
    adec_print("AudioTrack initCheck OK and started.");

    return 0;
}
status_t LibmediaPlayback::Play(int duration_secs) {
  audio_channel_mask_t audio_mask =
      audio_channel_out_mask_from_count(num_channels_);
  const audio_stream_type_t kStreamType = AUDIO_STREAM_MUSIC;
  size_t frame_count = 0;  // Use default value for frame count.
  audio_output_flags_t audio_output_flags = AUDIO_OUTPUT_FLAG_NONE;

  AudioTrack* track = new AudioTrack(
      kStreamType, sample_rate_, audio_format_, audio_mask, frame_count,
      audio_output_flags, LibmediaPlayback::AudioCallback,
      reinterpret_cast<void*>(this));
  status_t status = track->initCheck();
  if (status != OK) {
    LOG(ERROR) << "Audio track initialization failed.";
    return status;
  }

  float volume = 0.9;
  track->setVolume(volume);
  status = track->start();
  if (status != OK) {
    LOG(ERROR) << "Audio track failed to start.";
    return status;
  }

  sleep(duration_secs);
  track->stop();

  if (in_file_)
    sf_close(in_file_);
  else
    sine_data_buffer_->release();

  return status;
}
int
sa_stream_open(sa_stream_t *s) {

  if (s == NULL) {
    return SA_ERROR_NO_INIT;
  }
  if (s->output_unit != NULL) {
    return SA_ERROR_INVALID;
  }

  int32_t chanConfig = s->channels == 1 ?
    AudioSystem::CHANNEL_OUT_MONO : AudioSystem::CHANNEL_OUT_STEREO;

  int frameCount;
  if (AudioTrack::getMinFrameCount(&frameCount, AudioSystem::DEFAULT,
                                   s->rate) != NO_ERROR) {
    return SA_ERROR_INVALID;
  }
  int minsz = frameCount * s->channels * sizeof(int16_t);

  s->bufferSize = s->rate * s->channels * sizeof(int16_t);
  if (s->bufferSize < minsz) {
    s->bufferSize = minsz;
  }

  AudioTrack *track =
    new AudioTrack(AudioSystem::SYSTEM,
                   s->rate,
                   AudioSystem::PCM_16_BIT,
                   chanConfig,
                   frameCount,
                   0,
                   NULL, NULL,
                   0,
                   0);

  if (track->initCheck() != NO_ERROR) {
    delete track;
    return SA_ERROR_INVALID;
  }

  s->output_unit = track;

  ALOG("%p - New stream %u %u bsz=%u min=%u", s, s->rate, s->channels,
       s->bufferSize, minsz);

  return SA_SUCCESS;
}
Example #4
0
status_t APlaybackDevice::open()
{
    status_t err;
    int sampleRateInHz;
    int channelConfig;
    int audioFormat;
    int bufferSizeInBytes;

    LOG_FUNC_START

    sampleRateInHz = mDevice->Frequency;
    channelConfig = aluChannelsFromFormat(mDevice->Format) == 1 ?
        AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;

    audioFormat = aluBytesFromFormat(mDevice->Format) == 1 ?
        AUDIO_FORMAT_PCM_8_BIT : AUDIO_FORMAT_PCM_16_BIT;

    err = AudioTrack::getMinFrameCount(&bufferSizeInBytes, audioFormat, sampleRateInHz);
    RETURN_IF(err);

    LOGV("rate(%i), channel(%i), format(%i), buffSize(%i), numUpdates(%i)",
        sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mDevice->NumUpdates);

    err = mAudioTrack.set(AUDIO_STREAM_MUSIC,
                          sampleRateInHz,
                          audioFormat,
                          channelConfig,
                          bufferSizeInBytes,     // frameCount
                          0,                     // flags
                          0, 0);                 // callback, callback data (user)
    RETURN_IF(err);

    err = mAudioTrack.initCheck();
    RETURN_IF(err);

    if(mBuffer) {
        delete mBuffer;
    }
    mBuffer = new AAudioBuffer(bufferSizeInBytes);

    LOG_FUNC_END

    return NO_ERROR;
}
Example #5
0
status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
{
    // Check argument "bufferCount" against the mininum buffer count
    if (bufferCount < mMinBufferCount) {
        LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
        bufferCount = mMinBufferCount;

    }
    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
    if (mTrack) close();
    int afSampleRate;
    int afFrameCount;
    int frameCount;

    if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
        return NO_INIT;
    }
    if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
        return NO_INIT;
    }

    frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount);
    if ((t == 0) || (t->initCheck() != NO_ERROR)) {
        LOGE("Unable to create audio track");
        delete t;
        return NO_INIT;
    }

    LOGV("setVolume");
    t->setVolume(mLeftVolume, mRightVolume);
    mMsecsPerFrame = 1.e3 / (float) sampleRate;
    mLatency = t->latency() + kAudioVideoDelayMs;
    mTrack = t;
    return NO_ERROR;
}
void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
        float rightVolume, int priority, int loop, float rate)
{
    AudioTrack* oldTrack;

    LOGV("play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
            this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, priority, loop, rate);

    // if not idle, this voice is being stolen
    if (mState != IDLE) {
        LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
        mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
        stop();
        return;
    }

    // initialize track
    int afFrameCount;
    int afSampleRate;
    int streamType = mSoundPool->streamType();
    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
        afFrameCount = kDefaultFrameCount;
    }
    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
        afSampleRate = kDefaultSampleRate;
    }
    int numChannels = sample->numChannels();
    uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
    uint32_t bufferFrames = (afFrameCount * sampleRate) / afSampleRate;
    uint32_t frameCount = 0;

    if (loop) {
        frameCount = sample->size()/numChannels/((sample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
    }

#ifndef USE_SHARED_MEM_BUFFER
    // Ensure minimum audio buffer size in case of short looped sample
    if(frameCount < kDefaultBufferCount * bufferFrames) {
        frameCount = kDefaultBufferCount * bufferFrames;
    }
#endif

    AudioTrack* newTrack;
    
    // mToggle toggles each time a track is started on a given channel.
    // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
    // as callback user data. This enables the detection of callbacks received from the old
    // audio track while the new one is being started and avoids processing them with 
    // wrong audio audio buffer size  (mAudioBufferSize)
    unsigned long toggle = mToggle ^ 1;
    void *userData = (void *)((unsigned long)this | toggle);
    
#ifdef USE_SHARED_MEM_BUFFER
    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
            numChannels, sample->getIMemory(), 0, callback, userData);
#else
    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
            numChannels, frameCount, 0, callback, userData, bufferFrames);
#endif
    if (newTrack->initCheck() != NO_ERROR) {
        LOGE("Error creating AudioTrack");
        delete newTrack;
        return;
    }
    LOGV("setVolume %p", newTrack);
    newTrack->setVolume(leftVolume, rightVolume);
    newTrack->setLoop(0, frameCount, loop);

    {
        Mutex::Autolock lock(&mLock);
        // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored.
        mToggle = toggle;
        oldTrack = mAudioTrack;
        mAudioTrack = newTrack;
        mPos = 0;
        mSample = sample;
        mChannelID = nextChannelID;
        mPriority = priority;
        mLoop = loop;
        mLeftVolume = leftVolume;
        mRightVolume = rightVolume;
        mNumChannels = numChannels;
        mRate = rate;
        clearNextEvent();
        mState = PLAYING;
        mAudioTrack->start();
        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
    }

    LOGV("delete oldTrack %p", oldTrack);
    delete oldTrack;
}