/** * \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; }
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; }
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; }