mirror of https://github.com/axmolengine/axmol.git
Fixes crash while invoking pause&resume right after play2d. (#16406)
This commit is contained in:
parent
0fbc404cd9
commit
727c501285
|
@ -96,6 +96,60 @@ static void removeItemFromVector(std::vector<T>& v, T item)
|
|||
}
|
||||
}
|
||||
|
||||
void AudioMixerController::initTrack(Track* track, std::vector<Track*>& tracksToRemove)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// If we could not get the track name, it means that there're MAX_NUM_TRACKS tracks
|
||||
// So ignore the new track.
|
||||
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->setState(Track::State::PLAYING);
|
||||
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;
|
||||
|
@ -140,60 +194,17 @@ void AudioMixerController::mixOneFrame()
|
|||
|
||||
if (state == Track::State::IDLE)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// If we could not get the track name, it means that there're MAX_NUM_TRACKS tracks
|
||||
// So ignore the new track.
|
||||
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->setState(Track::State::PLAYING);
|
||||
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);
|
||||
}
|
||||
initTrack(track, tracksToRemove);
|
||||
}
|
||||
else if (state == Track::State::PLAYING)
|
||||
{
|
||||
ALOG_ASSERT(track->getName() >= 0);
|
||||
if (!track->isInitialized())
|
||||
{
|
||||
initTrack(track, tracksToRemove);
|
||||
}
|
||||
|
||||
int name = track->getName();
|
||||
ALOG_ASSERT(name >= 0);
|
||||
|
||||
std::lock_guard<std::mutex> lk(track->_volumeDirtyMutex);
|
||||
|
||||
|
@ -213,6 +224,11 @@ void AudioMixerController::mixOneFrame()
|
|||
}
|
||||
else if (state == Track::State::RESUMED)
|
||||
{
|
||||
if (!track->isInitialized())
|
||||
{
|
||||
initTrack(track, tracksToRemove);
|
||||
}
|
||||
|
||||
if (track->getPrevState() == Track::State::PAUSED)
|
||||
{
|
||||
_mixer->enable(track->getName());
|
||||
|
@ -220,29 +236,41 @@ void AudioMixerController::mixOneFrame()
|
|||
}
|
||||
else
|
||||
{
|
||||
ALOGW("Previous state (%d) isn't PAUSED, couldn't resume!", track->getPrevState());
|
||||
ALOGW("Previous state (%d) isn't PAUSED, couldn't resume!", static_cast<int>(track->getPrevState()));
|
||||
}
|
||||
}
|
||||
else if (state == Track::State::PAUSED)
|
||||
{
|
||||
if (!track->isInitialized())
|
||||
{
|
||||
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!", track->getPrevState());
|
||||
ALOGW("Previous state (%d) isn't PLAYING, couldn't pause!", static_cast<int>(track->getPrevState()));
|
||||
}
|
||||
}
|
||||
else if (state == Track::State::STOPPED)
|
||||
{
|
||||
if (track->getPrevState() != Track::State::IDLE)
|
||||
if (track->isInitialized())
|
||||
{
|
||||
_mixer->deleteTrackName(track->getName());
|
||||
if (track->getPrevState() != Track::State::IDLE)
|
||||
{
|
||||
_mixer->deleteTrackName(track->getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
ALOGV("Stop track (%p) while it's in IDLE state!", track);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ALOGV("Stop track (%p) while it's in IDLE state!", track);
|
||||
ALOGV("Track (%p) hasn't been initialized yet!", track);
|
||||
}
|
||||
tracksToRemove.push_back(track);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ public:
|
|||
bool init();
|
||||
|
||||
bool addTrack(Track* track);
|
||||
|
||||
bool hasPlayingTacks();
|
||||
|
||||
void pause();
|
||||
|
@ -67,6 +66,7 @@ public:
|
|||
|
||||
private:
|
||||
void destroy();
|
||||
void initTrack(Track* track, std::vector<Track*>& tracksToRemove);
|
||||
|
||||
private:
|
||||
int _bufferSizeInFrames;
|
||||
|
|
|
@ -40,6 +40,7 @@ Track::Track(const PcmData &pcmData)
|
|||
, _volume(1.0f)
|
||||
, _isVolumeDirty(true)
|
||||
, _isLoop(false)
|
||||
, _isInitialized(false)
|
||||
{
|
||||
init(_pcmData.pcmBuffer->data(), _pcmData.numFrames, _pcmData.bitsPerSample / 8 * _pcmData.numChannels);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,12 @@ private:
|
|||
inline void setVolumeDirty(bool isDirty)
|
||||
{ _isVolumeDirty = isDirty; };
|
||||
|
||||
inline bool isInitialized() const
|
||||
{ return _isInitialized; };
|
||||
|
||||
inline void setInitialized(bool isInitialized)
|
||||
{ _isInitialized = isInitialized; };
|
||||
|
||||
private:
|
||||
PcmData _pcmData;
|
||||
State _prevState;
|
||||
|
@ -89,6 +95,7 @@ private:
|
|||
bool _isVolumeDirty;
|
||||
std::mutex _volumeDirtyMutex;
|
||||
bool _isLoop;
|
||||
bool _isInitialized;
|
||||
|
||||
friend class AudioMixerController;
|
||||
};
|
||||
|
|
|
@ -42,6 +42,7 @@ AudioEngineTests::AudioEngineTests()
|
|||
ADD_TEST_CASE(AudioPerformanceTest);
|
||||
ADD_TEST_CASE(AudioSwitchStateTest);
|
||||
ADD_TEST_CASE(AudioSmallFileTest);
|
||||
ADD_TEST_CASE(AudioPauseResumeAfterPlay);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -803,3 +804,27 @@ std::string AudioSmallFileTest::subtitle() const
|
|||
{
|
||||
return "Should not crash";
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool AudioPauseResumeAfterPlay::init()
|
||||
{
|
||||
if (AudioEngineTestDemo::init())
|
||||
{
|
||||
int audioId = AudioEngine::play2d("audio/SoundEffectsFX009/FX082.mp3");
|
||||
AudioEngine::pause(audioId);
|
||||
AudioEngine::resume(audioId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string AudioPauseResumeAfterPlay::title() const
|
||||
{
|
||||
return "pause & resume right after play2d";
|
||||
}
|
||||
|
||||
std::string AudioPauseResumeAfterPlay::subtitle() const
|
||||
{
|
||||
return "Should not crash";
|
||||
}
|
||||
|
|
|
@ -199,4 +199,15 @@ public:
|
|||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
class AudioPauseResumeAfterPlay : public AudioEngineTestDemo
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(AudioPauseResumeAfterPlay);
|
||||
|
||||
virtual bool init() override;
|
||||
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
};
|
||||
|
||||
#endif /* defined(__NEWAUDIOENGINE_TEST_H_) */
|
||||
|
|
Loading…
Reference in New Issue