[big refactoring] Audio latency fix for Android. Support to preload effects on Android now. (#15875)
* Audio latency fix for Android. Support preload effects on Android now.
Squashed commits:
[b6d80fe] log fix
[a0a918e] Fixes assetFd didn't be released while PcmData is returned from cache.
[4b956ba] Potential crash fix for PcmAudioPlayer while pause / resume.
[398ab8c] Updates LOG_TAG position in AudioEngine-inl.cpp
[e3634e7] include stdlib.h for posix_memalign
[9004074] fixes setVolume logical error.
[c96df46] Don't use another thread for mixing, enqueue is in a seperated thread, therefore doing mixing in another thread will waste more time.
[0a4c1a8] Adds setLoop, setVolume, setPostion support for Track
[c35fb20] Fixed include.
[cdd9d32] Do mixing by ourself. (TO BE POLISHED)
[6447025] µ -> u since µ could not be shown on some android devices.
[97be0c6] Don't send a silence clip.
[c1607ed] Make linter.py happy.
[0898b54] Puts enqueue & SetPlayState in PcmAudioPlayer::play to thread pool.
[b79fc01] Adds getDuration, getPosition support for PcmAudioPlayer
[80fa2ab] minor fix of the code position of resetting state to State::INITIALIZED
[d9c62f1] underrun fix for PcmAudioPlayer.
[9c2212a] UrlAudioPlayer, playOverMutex should be static, and should be used in update method.
[1519d2e] static variables
[19da936] _pcmAudioPlayer Null pointer check in AudioPlayerProvider.
[e6b0d14] Updates audio performance test.
[fc01dd4] Registers foreground & background event in AudioEngine-inl.cpp(android), the callback should invoke `provider`'s pause & resume method.
[e00a886] TBD: Pause & resume support for PcmAudioPlayerPool.
Since OpenSLES audio resources are expensive and device shared, we should delete all unused PcmAudioPlayers in pool while pause and re-create them while resume.
But this commit isn't finished yet, I don't find a better way to register pause&resume event in AudioEngine module.
[9e42ea3] Interleave mono audio to stereo audio. PcmAudioPlayerPool only contains PcmAudioPlayers with 2 channels.
[3f18d05] Adds a strategy for checking small size of different file formats.
[753ff49] Adds performance test for AudioEngine.
[09d3045] Releases an extra PcmAudioPlayer for UrlAudioPlayer while allocating PcmAudioPlayer fails.
[9dd4477] Using std::move for PcmData move constructor & move assignment.
[6ca3bcb] some fixes:
1) new -> new (std::nothrow)
2) break if allocate PcmAudioPlayer fails
3) renames 'initForPlayPcmData' to 'init'
4) PcmAudioPlayer destructor deadlock if 'init' failed
[54675b6] include path fix.
[a1903ca] More refactorings.
[19b9498] Makes linter.py happy. :)
[923c530] Fixes:
1) Avoid getFileInfo to be invoked twice
2) A critical bug fix for UrlAudioPlayer and adds detailed comments
3) __clang__ compiler option fix for AudioResamplerSinc.cpp.
[5ec4faf] minor fix.
[faaa0f3] output a log in the destructor of UrlAudioPlayer.
[9c20355] NewAudioEngineTest,TestControll crash fix.
[f114464] fixes an unused import.
[1dc5dab] Better algorithm for allocating PcmAudioPlayer.
[331a213] minor fix.
[e54084a] null -> nullptr
[f9a0389] Support uncache.
[89a364f] Removes unused update, and TODO uncache functionality.
[1732bf9] Supports AudioEngineImpl::setFinishCallback for android.
[43d1596] UrlAudioPlayer::stop fix.
[e2ee941] Test case fix in NewAudioEngineTest/AudioIssue11143Test
[5c5ba01] More fixes for making cpp-tests/New Audio Engine Test happy.
[8b554a3] Adds log while remove player from map.
[ed71322] If original file is larger than 30k bytes, consider it's a large audio file.
[fb1845a] Updates project.properties
[6f3839f] minor log output fix in AudioEngine-inl.cpp
[c68bc6c] Don't resample if the sample rate of the decoded pcm data matchs the device's.
[43ca45f] PcmAudioPlayers also need to be removed while they play over, but should not be deleted since their lifecycle is managed by PcmAudioPlayerPool.
[f5e63c9] Audio latency fix for Android. Support preload effects on Android now.
* Supports to loading audio files asynchronously.
* Crash fix for stop audio right after play2d.
* Minor fix for logic in AudioMixerController.cpp
* Adds missing files (CCThreadPool.h/.cpp).
* Minor fix for including.
* Minor fix for missing include <functional> in Track.h
* update license information in audio.h
* Don't use std::future/std::promise anymore since ndk counldn't support it well in armeabi arch.
* isSmallFile postion updated, fixes large audio file goto the checking logic of cache.
* std::atomic<int> isn't supported by ndk-r10e while compiling with `armeabi` arch, using a int with a mutex instead.
* fixes __isnanf & posix_memalign doesn't exist on low api (<=16) devices.
* namespace updated: cocos2d -> cocos2d::experimental
* Removes commented code in AudioMixerController.h/.cpp
* Removes unused code again, and fixes a memory leak of `Track` instance.
* Oops, namespace changed.
* Only outputs log in debug mode.
* Uses ALOGV for outputing logs in AudioEngine-inl.cpp
* const PcmData& -> PcmData for Track
* Fixes a protential crash in NewAudioEngineTest
* Adds `COCOS` prefix in header #ifndef COCOS_BALABALA #define COCOS_BALABALA
* Uses _ prefix for cocos code style instead of `m` prefix.
* Deletes AudioResamplerSinc related files.
* Bug fix from @minggo's reply on github.
* Don't need to invoke pause after in UrlAudioPlayer::prepare.
* Updates ThreadPool class, uses enum class and adds const keyword.
2016-07-18 10:22:40 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "audio/android/cutils/log.h"
|
|
|
|
|
2019-10-23 14:58:31 +08:00
|
|
|
namespace cocos2d {
|
[big refactoring] Audio latency fix for Android. Support to preload effects on Android now. (#15875)
* Audio latency fix for Android. Support preload effects on Android now.
Squashed commits:
[b6d80fe] log fix
[a0a918e] Fixes assetFd didn't be released while PcmData is returned from cache.
[4b956ba] Potential crash fix for PcmAudioPlayer while pause / resume.
[398ab8c] Updates LOG_TAG position in AudioEngine-inl.cpp
[e3634e7] include stdlib.h for posix_memalign
[9004074] fixes setVolume logical error.
[c96df46] Don't use another thread for mixing, enqueue is in a seperated thread, therefore doing mixing in another thread will waste more time.
[0a4c1a8] Adds setLoop, setVolume, setPostion support for Track
[c35fb20] Fixed include.
[cdd9d32] Do mixing by ourself. (TO BE POLISHED)
[6447025] µ -> u since µ could not be shown on some android devices.
[97be0c6] Don't send a silence clip.
[c1607ed] Make linter.py happy.
[0898b54] Puts enqueue & SetPlayState in PcmAudioPlayer::play to thread pool.
[b79fc01] Adds getDuration, getPosition support for PcmAudioPlayer
[80fa2ab] minor fix of the code position of resetting state to State::INITIALIZED
[d9c62f1] underrun fix for PcmAudioPlayer.
[9c2212a] UrlAudioPlayer, playOverMutex should be static, and should be used in update method.
[1519d2e] static variables
[19da936] _pcmAudioPlayer Null pointer check in AudioPlayerProvider.
[e6b0d14] Updates audio performance test.
[fc01dd4] Registers foreground & background event in AudioEngine-inl.cpp(android), the callback should invoke `provider`'s pause & resume method.
[e00a886] TBD: Pause & resume support for PcmAudioPlayerPool.
Since OpenSLES audio resources are expensive and device shared, we should delete all unused PcmAudioPlayers in pool while pause and re-create them while resume.
But this commit isn't finished yet, I don't find a better way to register pause&resume event in AudioEngine module.
[9e42ea3] Interleave mono audio to stereo audio. PcmAudioPlayerPool only contains PcmAudioPlayers with 2 channels.
[3f18d05] Adds a strategy for checking small size of different file formats.
[753ff49] Adds performance test for AudioEngine.
[09d3045] Releases an extra PcmAudioPlayer for UrlAudioPlayer while allocating PcmAudioPlayer fails.
[9dd4477] Using std::move for PcmData move constructor & move assignment.
[6ca3bcb] some fixes:
1) new -> new (std::nothrow)
2) break if allocate PcmAudioPlayer fails
3) renames 'initForPlayPcmData' to 'init'
4) PcmAudioPlayer destructor deadlock if 'init' failed
[54675b6] include path fix.
[a1903ca] More refactorings.
[19b9498] Makes linter.py happy. :)
[923c530] Fixes:
1) Avoid getFileInfo to be invoked twice
2) A critical bug fix for UrlAudioPlayer and adds detailed comments
3) __clang__ compiler option fix for AudioResamplerSinc.cpp.
[5ec4faf] minor fix.
[faaa0f3] output a log in the destructor of UrlAudioPlayer.
[9c20355] NewAudioEngineTest,TestControll crash fix.
[f114464] fixes an unused import.
[1dc5dab] Better algorithm for allocating PcmAudioPlayer.
[331a213] minor fix.
[e54084a] null -> nullptr
[f9a0389] Support uncache.
[89a364f] Removes unused update, and TODO uncache functionality.
[1732bf9] Supports AudioEngineImpl::setFinishCallback for android.
[43d1596] UrlAudioPlayer::stop fix.
[e2ee941] Test case fix in NewAudioEngineTest/AudioIssue11143Test
[5c5ba01] More fixes for making cpp-tests/New Audio Engine Test happy.
[8b554a3] Adds log while remove player from map.
[ed71322] If original file is larger than 30k bytes, consider it's a large audio file.
[fb1845a] Updates project.properties
[6f3839f] minor log output fix in AudioEngine-inl.cpp
[c68bc6c] Don't resample if the sample rate of the decoded pcm data matchs the device's.
[43ca45f] PcmAudioPlayers also need to be removed while they play over, but should not be deleted since their lifecycle is managed by PcmAudioPlayerPool.
[f5e63c9] Audio latency fix for Android. Support preload effects on Android now.
* Supports to loading audio files asynchronously.
* Crash fix for stop audio right after play2d.
* Minor fix for logic in AudioMixerController.cpp
* Adds missing files (CCThreadPool.h/.cpp).
* Minor fix for including.
* Minor fix for missing include <functional> in Track.h
* update license information in audio.h
* Don't use std::future/std::promise anymore since ndk counldn't support it well in armeabi arch.
* isSmallFile postion updated, fixes large audio file goto the checking logic of cache.
* std::atomic<int> isn't supported by ndk-r10e while compiling with `armeabi` arch, using a int with a mutex instead.
* fixes __isnanf & posix_memalign doesn't exist on low api (<=16) devices.
* namespace updated: cocos2d -> cocos2d::experimental
* Removes commented code in AudioMixerController.h/.cpp
* Removes unused code again, and fixes a memory leak of `Track` instance.
* Oops, namespace changed.
* Only outputs log in debug mode.
* Uses ALOGV for outputing logs in AudioEngine-inl.cpp
* const PcmData& -> PcmData for Track
* Fixes a protential crash in NewAudioEngineTest
* Adds `COCOS` prefix in header #ifndef COCOS_BALABALA #define COCOS_BALABALA
* Uses _ prefix for cocos code style instead of `m` prefix.
* Deletes AudioResamplerSinc related files.
* Bug fix from @minggo's reply on github.
* Don't need to invoke pause after in UrlAudioPlayer::prepare.
* Updates ThreadPool class, uses enum class and adds const keyword.
2016-07-18 10:22:40 +08:00
|
|
|
|
|
|
|
/* Behavior of is_same<>::value is true if the types are identical,
|
|
|
|
* false otherwise. Identical to the STL std::is_same.
|
|
|
|
*/
|
|
|
|
template<typename T, typename U>
|
|
|
|
struct is_same
|
|
|
|
{
|
|
|
|
static const bool value = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct is_same<T, T> // partial specialization
|
|
|
|
{
|
|
|
|
static const bool value = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* MixMul is a multiplication operator to scale an audio input signal
|
|
|
|
* by a volume gain, with the formula:
|
|
|
|
*
|
|
|
|
* O(utput) = I(nput) * V(olume)
|
|
|
|
*
|
|
|
|
* The output, input, and volume may have different types.
|
|
|
|
* There are 27 variants, of which 14 are actually defined in an
|
|
|
|
* explicitly templated class.
|
|
|
|
*
|
|
|
|
* The following type variables and the underlying meaning:
|
|
|
|
*
|
|
|
|
* Output type TO: int32_t (Q4.27) or int16_t (Q.15) or float [-1,1]
|
|
|
|
* Input signal type TI: int32_t (Q4.27) or int16_t (Q.15) or float [-1,1]
|
|
|
|
* Volume type TV: int32_t (U4.28) or int16_t (U4.12) or float [-1,1]
|
|
|
|
*
|
|
|
|
* For high precision audio, only the <TO, TI, TV> = <float, float, float>
|
|
|
|
* needs to be accelerated. This is perhaps the easiest form to do quickly as well.
|
|
|
|
*
|
|
|
|
* A generic version is NOT defined to catch any mistake of using it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename TO, typename TI, typename TV>
|
|
|
|
TO MixMul(TI value, TV volume);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int32_t MixMul<int32_t, int16_t, int16_t>(int16_t value, int16_t volume) {
|
|
|
|
return value * volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int32_t MixMul<int32_t, int32_t, int16_t>(int32_t value, int16_t volume) {
|
|
|
|
return (value >> 12) * volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int32_t MixMul<int32_t, int16_t, int32_t>(int16_t value, int32_t volume) {
|
|
|
|
return value * (volume >> 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int32_t MixMul<int32_t, int32_t, int32_t>(int32_t value, int32_t volume) {
|
|
|
|
return (value >> 12) * (volume >> 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline float MixMul<float, float, int16_t>(float value, int16_t volume) {
|
|
|
|
static const float norm = 1. / (1 << 12);
|
|
|
|
return value * volume * norm;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline float MixMul<float, float, int32_t>(float value, int32_t volume) {
|
|
|
|
static const float norm = 1. / (1 << 28);
|
|
|
|
return value * volume * norm;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, float, int16_t>(float value, int16_t volume) {
|
|
|
|
return clamp16_from_float(MixMul<float, float, int16_t>(value, volume));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, float, int32_t>(float value, int32_t volume) {
|
|
|
|
return clamp16_from_float(MixMul<float, float, int32_t>(value, volume));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline float MixMul<float, int16_t, int16_t>(int16_t value, int16_t volume) {
|
|
|
|
static const float norm = 1. / (1 << (15 + 12));
|
|
|
|
return static_cast<float>(value) * static_cast<float>(volume) * norm;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline float MixMul<float, int16_t, int32_t>(int16_t value, int32_t volume) {
|
|
|
|
static const float norm = 1. / (1ULL << (15 + 28));
|
|
|
|
return static_cast<float>(value) * static_cast<float>(volume) * norm;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, int16_t, int16_t>(int16_t value, int16_t volume) {
|
|
|
|
return clamp16(MixMul<int32_t, int16_t, int16_t>(value, volume) >> 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, int32_t, int16_t>(int32_t value, int16_t volume) {
|
|
|
|
return clamp16(MixMul<int32_t, int32_t, int16_t>(value, volume) >> 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, int16_t, int32_t>(int16_t value, int32_t volume) {
|
|
|
|
return clamp16(MixMul<int32_t, int16_t, int32_t>(value, volume) >> 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, int32_t, int32_t>(int32_t value, int32_t volume) {
|
|
|
|
return clamp16(MixMul<int32_t, int32_t, int32_t>(value, volume) >> 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Required for floating point volume. Some are needed for compilation but
|
|
|
|
* are not needed in execution and should be removed from the final build by
|
|
|
|
* an optimizing compiler.
|
|
|
|
*/
|
|
|
|
template <>
|
|
|
|
inline float MixMul<float, float, float>(float value, float volume) {
|
|
|
|
return value * volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline float MixMul<float, int16_t, float>(int16_t value, float volume) {
|
|
|
|
static const float float_from_q_15 = 1. / (1 << 15);
|
|
|
|
return value * volume * float_from_q_15;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int32_t MixMul<int32_t, int32_t, float>(int32_t value, float volume) {
|
|
|
|
LOG_ALWAYS_FATAL("MixMul<int32_t, int32_t, float> Runtime Should not be here");
|
|
|
|
return value * volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int32_t MixMul<int32_t, int16_t, float>(int16_t value, float volume) {
|
|
|
|
LOG_ALWAYS_FATAL("MixMul<int32_t, int16_t, float> Runtime Should not be here");
|
|
|
|
static const float u4_12_from_float = (1 << 12);
|
|
|
|
return value * volume * u4_12_from_float;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, int16_t, float>(int16_t value, float volume) {
|
|
|
|
LOG_ALWAYS_FATAL("MixMul<int16_t, int16_t, float> Runtime Should not be here");
|
|
|
|
return clamp16_from_float(MixMul<float, int16_t, float>(value, volume));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int16_t MixMul<int16_t, float, float>(float value, float volume) {
|
|
|
|
return clamp16_from_float(value * volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MixAccum is used to add into an accumulator register of a possibly different
|
|
|
|
* type. The TO and TI types are the same as MixMul.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename TO, typename TI>
|
|
|
|
inline void MixAccum(TO *auxaccum, TI value) {
|
|
|
|
if (!is_same<TO, TI>::value) {
|
|
|
|
LOG_ALWAYS_FATAL("MixAccum type not properly specialized: %zu %zu\n",
|
|
|
|
sizeof(TO), sizeof(TI));
|
|
|
|
}
|
|
|
|
*auxaccum += value;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline void MixAccum<float, int16_t>(float *auxaccum, int16_t value) {
|
|
|
|
static const float norm = 1. / (1 << 15);
|
|
|
|
*auxaccum += norm * value;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline void MixAccum<float, int32_t>(float *auxaccum, int32_t value) {
|
|
|
|
static const float norm = 1. / (1 << 27);
|
|
|
|
*auxaccum += norm * value;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline void MixAccum<int32_t, int16_t>(int32_t *auxaccum, int16_t value) {
|
|
|
|
*auxaccum += value << 12;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline void MixAccum<int32_t, float>(int32_t *auxaccum, float value) {
|
|
|
|
*auxaccum += clampq4_27_from_float(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MixMulAux is just like MixMul except it combines with
|
|
|
|
* an accumulator operation MixAccum.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename TO, typename TI, typename TV, typename TA>
|
|
|
|
inline TO MixMulAux(TI value, TV volume, TA *auxaccum) {
|
|
|
|
MixAccum<TA, TI>(auxaccum, value);
|
|
|
|
return MixMul<TO, TI, TV>(value, volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MIXTYPE is used to determine how the samples in the input frame
|
|
|
|
* are mixed with volume gain into the output frame.
|
|
|
|
* See the volumeRampMulti functions below for more details.
|
|
|
|
*/
|
|
|
|
enum {
|
|
|
|
MIXTYPE_MULTI,
|
|
|
|
MIXTYPE_MONOEXPAND,
|
|
|
|
MIXTYPE_MULTI_SAVEONLY,
|
|
|
|
MIXTYPE_MULTI_MONOVOL,
|
|
|
|
MIXTYPE_MULTI_SAVEONLY_MONOVOL,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The volumeRampMulti and volumeRamp functions take a MIXTYPE
|
|
|
|
* which indicates the per-frame mixing and accumulation strategy.
|
|
|
|
*
|
|
|
|
* MIXTYPE_MULTI:
|
|
|
|
* NCHAN represents number of input and output channels.
|
|
|
|
* TO: int32_t (Q4.27) or float
|
|
|
|
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float
|
|
|
|
* TV: int32_t (U4.28) or int16_t (U4.12) or float
|
|
|
|
* vol: represents a volume array.
|
|
|
|
*
|
|
|
|
* This accumulates into the out pointer.
|
|
|
|
*
|
|
|
|
* MIXTYPE_MONOEXPAND:
|
|
|
|
* Single input channel. NCHAN represents number of output channels.
|
|
|
|
* TO: int32_t (Q4.27) or float
|
|
|
|
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float
|
|
|
|
* TV: int32_t (U4.28) or int16_t (U4.12) or float
|
|
|
|
* Input channel count is 1.
|
|
|
|
* vol: represents volume array.
|
|
|
|
*
|
|
|
|
* This accumulates into the out pointer.
|
|
|
|
*
|
|
|
|
* MIXTYPE_MULTI_SAVEONLY:
|
|
|
|
* NCHAN represents number of input and output channels.
|
|
|
|
* TO: int16_t (Q.15) or float
|
|
|
|
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float
|
|
|
|
* TV: int32_t (U4.28) or int16_t (U4.12) or float
|
|
|
|
* vol: represents a volume array.
|
|
|
|
*
|
|
|
|
* MIXTYPE_MULTI_SAVEONLY does not accumulate into the out pointer.
|
|
|
|
*
|
|
|
|
* MIXTYPE_MULTI_MONOVOL:
|
|
|
|
* Same as MIXTYPE_MULTI, but uses only volume[0].
|
|
|
|
*
|
|
|
|
* MIXTYPE_MULTI_SAVEONLY_MONOVOL:
|
|
|
|
* Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0].
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <int MIXTYPE, int NCHAN,
|
|
|
|
typename TO, typename TI, typename TV, typename TA, typename TAV>
|
|
|
|
inline void volumeRampMulti(TO* out, size_t frameCount,
|
|
|
|
const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
|
|
|
|
{
|
|
|
|
#ifdef ALOGVV
|
|
|
|
ALOGVV("volumeRampMulti, MIXTYPE:%d\n", MIXTYPE);
|
|
|
|
#endif
|
|
|
|
if (aux != NULL) {
|
|
|
|
do {
|
|
|
|
TA auxaccum = 0;
|
|
|
|
switch (MIXTYPE) {
|
|
|
|
case MIXTYPE_MULTI:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
|
|
|
|
vol[i] += volinc[i];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MONOEXPAND:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
|
|
|
|
vol[i] += volinc[i];
|
|
|
|
}
|
|
|
|
in++;
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
|
|
|
|
vol[i] += volinc[i];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
|
|
|
|
}
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
|
|
|
|
}
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
auxaccum /= NCHAN;
|
|
|
|
*aux++ += MixMul<TA, TA, TAV>(auxaccum, *vola);
|
|
|
|
vola[0] += volainc;
|
|
|
|
} while (--frameCount);
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
switch (MIXTYPE) {
|
|
|
|
case MIXTYPE_MULTI:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
|
|
|
|
vol[i] += volinc[i];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MONOEXPAND:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMul<TO, TI, TV>(*in, vol[i]);
|
|
|
|
vol[i] += volinc[i];
|
|
|
|
}
|
|
|
|
in++;
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
|
|
|
|
vol[i] += volinc[i];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMul<TO, TI, TV>(*in++, vol[0]);
|
|
|
|
}
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
|
|
|
|
}
|
|
|
|
vol[0] += volinc[0];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (--frameCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <int MIXTYPE, int NCHAN,
|
|
|
|
typename TO, typename TI, typename TV, typename TA, typename TAV>
|
|
|
|
inline void volumeMulti(TO* out, size_t frameCount,
|
|
|
|
const TI* in, TA* aux, const TV *vol, TAV vola)
|
|
|
|
{
|
|
|
|
#ifdef ALOGVV
|
|
|
|
ALOGVV("volumeMulti MIXTYPE:%d\n", MIXTYPE);
|
|
|
|
#endif
|
|
|
|
if (aux != NULL) {
|
|
|
|
do {
|
|
|
|
TA auxaccum = 0;
|
|
|
|
switch (MIXTYPE) {
|
|
|
|
case MIXTYPE_MULTI:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MONOEXPAND:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
|
|
|
|
}
|
|
|
|
in++;
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
auxaccum /= NCHAN;
|
|
|
|
*aux++ += MixMul<TA, TA, TAV>(auxaccum, vola);
|
|
|
|
} while (--frameCount);
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
switch (MIXTYPE) {
|
|
|
|
case MIXTYPE_MULTI:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MONOEXPAND:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMul<TO, TI, TV>(*in, vol[i]);
|
|
|
|
}
|
|
|
|
in++;
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ += MixMul<TO, TI, TV>(*in++, vol[0]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
|
|
|
|
for (int i = 0; i < NCHAN; ++i) {
|
|
|
|
*out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (--frameCount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 14:58:31 +08:00
|
|
|
} // namespace cocos2d {
|
[big refactoring] Audio latency fix for Android. Support to preload effects on Android now. (#15875)
* Audio latency fix for Android. Support preload effects on Android now.
Squashed commits:
[b6d80fe] log fix
[a0a918e] Fixes assetFd didn't be released while PcmData is returned from cache.
[4b956ba] Potential crash fix for PcmAudioPlayer while pause / resume.
[398ab8c] Updates LOG_TAG position in AudioEngine-inl.cpp
[e3634e7] include stdlib.h for posix_memalign
[9004074] fixes setVolume logical error.
[c96df46] Don't use another thread for mixing, enqueue is in a seperated thread, therefore doing mixing in another thread will waste more time.
[0a4c1a8] Adds setLoop, setVolume, setPostion support for Track
[c35fb20] Fixed include.
[cdd9d32] Do mixing by ourself. (TO BE POLISHED)
[6447025] µ -> u since µ could not be shown on some android devices.
[97be0c6] Don't send a silence clip.
[c1607ed] Make linter.py happy.
[0898b54] Puts enqueue & SetPlayState in PcmAudioPlayer::play to thread pool.
[b79fc01] Adds getDuration, getPosition support for PcmAudioPlayer
[80fa2ab] minor fix of the code position of resetting state to State::INITIALIZED
[d9c62f1] underrun fix for PcmAudioPlayer.
[9c2212a] UrlAudioPlayer, playOverMutex should be static, and should be used in update method.
[1519d2e] static variables
[19da936] _pcmAudioPlayer Null pointer check in AudioPlayerProvider.
[e6b0d14] Updates audio performance test.
[fc01dd4] Registers foreground & background event in AudioEngine-inl.cpp(android), the callback should invoke `provider`'s pause & resume method.
[e00a886] TBD: Pause & resume support for PcmAudioPlayerPool.
Since OpenSLES audio resources are expensive and device shared, we should delete all unused PcmAudioPlayers in pool while pause and re-create them while resume.
But this commit isn't finished yet, I don't find a better way to register pause&resume event in AudioEngine module.
[9e42ea3] Interleave mono audio to stereo audio. PcmAudioPlayerPool only contains PcmAudioPlayers with 2 channels.
[3f18d05] Adds a strategy for checking small size of different file formats.
[753ff49] Adds performance test for AudioEngine.
[09d3045] Releases an extra PcmAudioPlayer for UrlAudioPlayer while allocating PcmAudioPlayer fails.
[9dd4477] Using std::move for PcmData move constructor & move assignment.
[6ca3bcb] some fixes:
1) new -> new (std::nothrow)
2) break if allocate PcmAudioPlayer fails
3) renames 'initForPlayPcmData' to 'init'
4) PcmAudioPlayer destructor deadlock if 'init' failed
[54675b6] include path fix.
[a1903ca] More refactorings.
[19b9498] Makes linter.py happy. :)
[923c530] Fixes:
1) Avoid getFileInfo to be invoked twice
2) A critical bug fix for UrlAudioPlayer and adds detailed comments
3) __clang__ compiler option fix for AudioResamplerSinc.cpp.
[5ec4faf] minor fix.
[faaa0f3] output a log in the destructor of UrlAudioPlayer.
[9c20355] NewAudioEngineTest,TestControll crash fix.
[f114464] fixes an unused import.
[1dc5dab] Better algorithm for allocating PcmAudioPlayer.
[331a213] minor fix.
[e54084a] null -> nullptr
[f9a0389] Support uncache.
[89a364f] Removes unused update, and TODO uncache functionality.
[1732bf9] Supports AudioEngineImpl::setFinishCallback for android.
[43d1596] UrlAudioPlayer::stop fix.
[e2ee941] Test case fix in NewAudioEngineTest/AudioIssue11143Test
[5c5ba01] More fixes for making cpp-tests/New Audio Engine Test happy.
[8b554a3] Adds log while remove player from map.
[ed71322] If original file is larger than 30k bytes, consider it's a large audio file.
[fb1845a] Updates project.properties
[6f3839f] minor log output fix in AudioEngine-inl.cpp
[c68bc6c] Don't resample if the sample rate of the decoded pcm data matchs the device's.
[43ca45f] PcmAudioPlayers also need to be removed while they play over, but should not be deleted since their lifecycle is managed by PcmAudioPlayerPool.
[f5e63c9] Audio latency fix for Android. Support preload effects on Android now.
* Supports to loading audio files asynchronously.
* Crash fix for stop audio right after play2d.
* Minor fix for logic in AudioMixerController.cpp
* Adds missing files (CCThreadPool.h/.cpp).
* Minor fix for including.
* Minor fix for missing include <functional> in Track.h
* update license information in audio.h
* Don't use std::future/std::promise anymore since ndk counldn't support it well in armeabi arch.
* isSmallFile postion updated, fixes large audio file goto the checking logic of cache.
* std::atomic<int> isn't supported by ndk-r10e while compiling with `armeabi` arch, using a int with a mutex instead.
* fixes __isnanf & posix_memalign doesn't exist on low api (<=16) devices.
* namespace updated: cocos2d -> cocos2d::experimental
* Removes commented code in AudioMixerController.h/.cpp
* Removes unused code again, and fixes a memory leak of `Track` instance.
* Oops, namespace changed.
* Only outputs log in debug mode.
* Uses ALOGV for outputing logs in AudioEngine-inl.cpp
* const PcmData& -> PcmData for Track
* Fixes a protential crash in NewAudioEngineTest
* Adds `COCOS` prefix in header #ifndef COCOS_BALABALA #define COCOS_BALABALA
* Uses _ prefix for cocos code style instead of `m` prefix.
* Deletes AudioResamplerSinc related files.
* Bug fix from @minggo's reply on github.
* Don't need to invoke pause after in UrlAudioPlayer::prepare.
* Updates ThreadPool class, uses enum class and adds const keyword.
2016-07-18 10:22:40 +08:00
|
|
|
|