123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- #define LOG_TAG "AudioMixerController"
- #include "audio/android/AudioMixerController.h"
- #include "audio/android/AudioMixer.h"
- #include "audio/android/Track.h"
- #include "audio/android/OpenSLHelper.h"
- #include <algorithm>
- namespace cocos2d { namespace experimental {
- AudioMixerController::AudioMixerController(int bufferSizeInFrames, int sampleRate, int channelCount)
- : _bufferSizeInFrames(bufferSizeInFrames)
- , _sampleRate(sampleRate)
- , _channelCount(channelCount)
- , _mixer(nullptr)
- , _isPaused(false)
- , _isMixingFrame(false)
- {
- ALOGV("In the constructor of AudioMixerController!");
- _mixingBuffer.size = (size_t) bufferSizeInFrames * 2 * channelCount;
-
-
- _mixingBuffer.buf = memalign(32, _mixingBuffer.size);
- memset(_mixingBuffer.buf, 0, _mixingBuffer.size);
- }
- AudioMixerController::~AudioMixerController()
- {
- destroy();
- if (_mixer != nullptr)
- {
- delete _mixer;
- _mixer = nullptr;
- }
- free(_mixingBuffer.buf);
- }
- bool AudioMixerController::init()
- {
- _mixer = new (std::nothrow) AudioMixer(_bufferSizeInFrames, _sampleRate);
- return _mixer != nullptr;
- }
- bool AudioMixerController::addTrack(Track* track)
- {
- ALOG_ASSERT(track != nullptr, "Shouldn't pass nullptr to addTrack");
- bool ret = false;
- std::lock_guard<std::mutex> lk(_activeTracksMutex);
- auto iter = std::find(_activeTracks.begin(), _activeTracks.end(), track);
- if (iter == _activeTracks.end())
- {
- _activeTracks.push_back(track);
- ret = true;
- }
- return ret;
- }
- template <typename T>
- static void removeItemFromVector(std::vector<T>& v, T item)
- {
- auto iter = std::find(v.begin(), v.end(), item);
- if (iter != v.end())
- {
- v.erase(iter);
- }
- }
- void AudioMixerController::initTrack(Track* track, std::vector<Track*>& tracksToRemove)
- {
- if (track->isInitialized())
- return;
- uint32_t channelMask = audio_channel_out_mask_from_count(2);
- int32_t name = _mixer->getTrackName(channelMask, AUDIO_FORMAT_PCM_16_BIT,
- AUDIO_SESSION_OUTPUT_MIX);
- if (name < 0)
- {
-
-
- tracksToRemove.push_back(track);
- }
- else
- {
- _mixer->setBufferProvider(name, track);
- _mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
- _mixingBuffer.buf);
- _mixer->setParameter(
- name,
- AudioMixer::TRACK,
- AudioMixer::MIXER_FORMAT,
- (void *) (uintptr_t) AUDIO_FORMAT_PCM_16_BIT);
- _mixer->setParameter(
- name,
- AudioMixer::TRACK,
- AudioMixer::FORMAT,
- (void *) (uintptr_t) AUDIO_FORMAT_PCM_16_BIT);
- _mixer->setParameter(
- name,
- AudioMixer::TRACK,
- AudioMixer::MIXER_CHANNEL_MASK,
- (void *) (uintptr_t) channelMask);
- _mixer->setParameter(
- name,
- AudioMixer::TRACK,
- AudioMixer::CHANNEL_MASK,
- (void *) (uintptr_t) channelMask);
- track->setName(name);
- _mixer->enable(name);
- std::lock_guard<std::mutex> lk(track->_volumeDirtyMutex);
- gain_minifloat_packed_t volume = track->getVolumeLR();
- float lVolume = float_from_gain(gain_minifloat_unpack_left(volume));
- float rVolume = float_from_gain(gain_minifloat_unpack_right(volume));
- _mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &lVolume);
- _mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &rVolume);
- track->setVolumeDirty(false);
- track->setInitialized(true);
- }
- }
- void AudioMixerController::mixOneFrame()
- {
- _isMixingFrame = true;
- _activeTracksMutex.lock();
- auto mixStart = clockNow();
- std::vector<Track*> tracksToRemove;
- tracksToRemove.reserve(_activeTracks.size());
-
-
- Track::State state;
-
- for (auto&& track : _activeTracks)
- {
- state = track->getState();
- if (state == Track::State::PLAYING)
- {
- initTrack(track, tracksToRemove);
- int name = track->getName();
- ALOG_ASSERT(name >= 0);
- std::lock_guard<std::mutex> lk(track->_volumeDirtyMutex);
- if (track->isVolumeDirty())
- {
- gain_minifloat_packed_t volume = track->getVolumeLR();
- float lVolume = float_from_gain(gain_minifloat_unpack_left(volume));
- float rVolume = float_from_gain(gain_minifloat_unpack_right(volume));
- ALOGV("Track (name: %d)'s volume is dirty, update volume to L: %f, R: %f", name, lVolume, rVolume);
- _mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &lVolume);
- _mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &rVolume);
- track->setVolumeDirty(false);
- }
- }
- else if (state == Track::State::RESUMED)
- {
- initTrack(track, tracksToRemove);
- if (track->getPrevState() == Track::State::PAUSED)
- {
- _mixer->enable(track->getName());
- track->setState(Track::State::PLAYING);
- }
- else
- {
- ALOGW("Previous state (%d) isn't PAUSED, couldn't resume!", static_cast<int>(track->getPrevState()));
- }
- }
- else if (state == Track::State::PAUSED)
- {
- initTrack(track, tracksToRemove);
- if (track->getPrevState() == Track::State::PLAYING || track->getPrevState() == Track::State::RESUMED)
- {
- _mixer->disable(track->getName());
- }
- else
- {
- ALOGW("Previous state (%d) isn't PLAYING, couldn't pause!", static_cast<int>(track->getPrevState()));
- }
- }
- else if (state == Track::State::STOPPED)
- {
- if (track->isInitialized())
- {
- _mixer->deleteTrackName(track->getName());
- }
- else
- {
- ALOGV("Track (%p) hasn't been initialized yet!", track);
- }
- tracksToRemove.push_back(track);
- }
- if (track->isPlayOver())
- {
- if (track->isLoop())
- {
- track->reset();
- }
- else
- {
- ALOGV("Play over ...");
- _mixer->deleteTrackName(track->getName());
- tracksToRemove.push_back(track);
- track->setState(Track::State::OVER);
- }
- }
- }
- bool hasAvailableTracks = _activeTracks.size() - tracksToRemove.size() > 0;
- if (hasAvailableTracks)
- {
- ALOGV_IF(_activeTracks.size() > 8, "More than 8 active tracks: %d", (int) _activeTracks.size());
- _mixer->process(AudioBufferProvider::kInvalidPTS);
- }
- else
- {
- ALOGV("Doesn't have enough tracks: %d, %d", (int) _activeTracks.size(), (int) tracksToRemove.size());
- }
-
- for (auto&& track : tracksToRemove)
- {
- removeItemFromVector(_activeTracks, track);
- if (track != nullptr && track->onStateChanged != nullptr)
- {
- track->onStateChanged(Track::State::DESTROYED);
- }
- else
- {
- ALOGE("track (%p) was released ...", track);
- }
- }
- _activeTracksMutex.unlock();
- auto mixEnd = clockNow();
- float mixInterval = intervalInMS(mixStart, mixEnd);
- ALOGV_IF(mixInterval > 1.0f, "Mix a frame waste: %fms", mixInterval);
- _isMixingFrame = false;
- }
- void AudioMixerController::destroy()
- {
- while (_isMixingFrame)
- {
- usleep(10);
- }
- usleep(2000);
- }
- void AudioMixerController::pause()
- {
- _isPaused = true;
- }
- void AudioMixerController::resume()
- {
- _isPaused = false;
- }
- bool AudioMixerController::hasPlayingTacks()
- {
- std::lock_guard<std::mutex> lk (_activeTracksMutex);
- if (_activeTracks.empty())
- return false;
- for (auto&& track : _activeTracks)
- {
- Track::State state = track->getState();
- if (state == Track::State::IDLE || state == Track::State::PLAYING || state == Track::State::RESUMED)
- {
- return true;
- }
- }
- return false;
- }
- }}
|