mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Remove the return value from NativeMix, correct mixing with other channel numbers than 2
This commit is contained in:
1 parent
5ace3179f8
commit
0502d79c99
9 files changed
+55
-70
No files matched your search
@@ -59,13 +59,11 @@ void NativeMouseDelta(float dx, float dy);
|
||||
void NativeFrame(GraphicsContext *graphicsContext);
|
||||
|
||||
// This should render num_samples 44khz stereo samples.
|
||||
// Try not to make too many assumptions on the granularity
|
||||
// of num_samples.
|
||||
// This function may be called from a totally separate thread from
|
||||
// the rest of the game, so be careful with synchronization.
|
||||
// Returns the number of samples actually output. The app should do everything it can
|
||||
// to fill the buffer completely.
|
||||
int NativeMix(short *audio, int num_samples, int sampleRateHz, void *userdata);
|
||||
// Try not to make too many assumptions on the granularity of num_samples.
|
||||
// This function will likely be called from a totally separate thread from
|
||||
// the rest of the app, so be careful with synchronization.
|
||||
// The app must fill the buffer completely, doing its own internal buffering if needed.
|
||||
void NativeMix(short *audio, int num_samples, int sampleRateHz, void *userdata);
|
||||
|
||||
// Called when it's time to shutdown. After this has been called,
|
||||
// no more calls to any other function will be made from the framework
|
||||
|
||||
@@ -160,9 +160,9 @@ inline int16_t MixSingleSample(int16_t s1, int16_t s2, uint16_t frac) {
|
||||
}
|
||||
|
||||
// Executed from sound stream thread, pulling sound out of the buffer.
|
||||
unsigned int StereoResampler::Mix(short* samples, unsigned int numSamples, bool consider_framelimit, int sample_rate) {
|
||||
void StereoResampler::Mix(s16 *samples, unsigned int numSamples, bool consider_framelimit, int sample_rate) {
|
||||
if (!samples)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
unsigned int currentSample;
|
||||
|
||||
@@ -242,9 +242,6 @@ unsigned int StereoResampler::Mix(short* samples, unsigned int numSamples, bool
|
||||
|
||||
// Flush cached variable
|
||||
indexR_.store(indexR);
|
||||
|
||||
// TODO: What should we actually return here?
|
||||
return currentSample / 2;
|
||||
}
|
||||
|
||||
// Executes on the emulator thread, pushing sound into the buffer.
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
~StereoResampler();
|
||||
|
||||
// Called from audio threads
|
||||
unsigned int Mix(short* samples, unsigned int numSamples, bool consider_framelimit, int sampleRate);
|
||||
void Mix(s16 *samples, unsigned int numSamples, bool consider_framelimit, int sampleRate);
|
||||
|
||||
// Called from main thread
|
||||
// This clamps the samples to 16-bit before starting to work on them.
|
||||
|
||||
+2
-3
@@ -792,9 +792,8 @@ void MainAudio::run() {
|
||||
|
||||
void MainAudio::timerEvent(QTimerEvent *) {
|
||||
memset(mixbuf, 0, mixlen);
|
||||
size_t frames = NativeMix((short *)mixbuf, AUDIO_BUFFERS*AUDIO_SAMPLES, AUDIO_FREQ);
|
||||
if (frames > 0)
|
||||
feed->write(mixbuf, sizeof(short) * AUDIO_CHANNELS * frames);
|
||||
NativeMix((short *)mixbuf, AUDIO_BUFFERS * AUDIO_SAMPLES, AUDIO_FREQ);
|
||||
feed->write(mixbuf, sizeof(short) * AUDIO_CHANNELS * frames);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+3
-5
@@ -7,13 +7,11 @@ StereoResampler g_resampler;
|
||||
|
||||
// numFrames is number of stereo frames.
|
||||
// This is called from *outside* the emulator thread.
|
||||
int NativeMix(int16_t *outStereo, int numFrames, int sampleRateHz, void *userdata) {
|
||||
int validFrames = g_resampler.Mix(outStereo, numFrames, false, sampleRateHz);
|
||||
void NativeMix(int16_t *outStereo, int numFrames, int sampleRateHz, void *userdata) {
|
||||
g_resampler.Mix(outStereo, numFrames, false, sampleRateHz);
|
||||
|
||||
// Mix sound effects on top.
|
||||
g_BackgroundAudio.SFX().Mix(outStereo, validFrames, sampleRateHz);
|
||||
|
||||
return validFrames;
|
||||
g_BackgroundAudio.SFX().Mix(outStereo, numFrames, sampleRateHz);
|
||||
}
|
||||
|
||||
void System_AudioGetDebugStats(char *buf, size_t bufSize) {
|
||||
|
||||
+14
-6
@@ -803,19 +803,27 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
void CallbackPostRender(UIContext *dc, void *userdata);
|
||||
bool CreateGlobalPipelines();
|
||||
|
||||
// TODO: Add faster special case for channels == 2.
|
||||
void NativeMixWrapper(float *dest, int framesToWrite, int channels, int sampleRateHz, void *userdata) {
|
||||
static int16_t *buffer;
|
||||
static int bufSize;
|
||||
if (bufSize < framesToWrite * channels) {
|
||||
buffer = new int16_t[framesToWrite * channels];
|
||||
bufSize = framesToWrite * channels;
|
||||
if (bufSize < framesToWrite * 2) {
|
||||
buffer = new int16_t[framesToWrite * 2];
|
||||
bufSize = framesToWrite * 2;
|
||||
}
|
||||
|
||||
NativeMix(buffer, framesToWrite, sampleRateHz, userdata);
|
||||
|
||||
for (int i = 0; i < framesToWrite * channels; i++) {
|
||||
int16_t value = buffer[i];
|
||||
dest[i] = (float)value * (float)(1.0f / 32767.0f);
|
||||
for (int i = 0; i < framesToWrite; i++) {
|
||||
int16_t lvalue = buffer[i * 2];
|
||||
int16_t rvalue = buffer[i * 2 + 1];
|
||||
dest[i * channels] = (float)lvalue * (float)(1.0f / 32767.0f);
|
||||
if (channels > 1) {
|
||||
dest[i * channels + 1] = (float)lvalue * (float)(1.0f / 32767.0f);
|
||||
}
|
||||
for (int j = 2; j < channels; j++) {
|
||||
dest[i * channels + j] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "WASAPIContext.h"
|
||||
|
||||
static std::string ConvertWStringToUTF8(const std::wstring &wstr) {
|
||||
int len = (int)wstr.size();
|
||||
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
|
||||
const int len = (int)wstr.size();
|
||||
const int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
|
||||
std::string s;
|
||||
s.resize(size);
|
||||
if (size > 0) {
|
||||
@@ -24,8 +25,8 @@ static std::string ConvertWStringToUTF8(const std::wstring &wstr) {
|
||||
}
|
||||
|
||||
static std::wstring ConvertUTF8ToWString(const std::string_view source) {
|
||||
int len = (int)source.size();
|
||||
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.data(), len, NULL, 0);
|
||||
const int len = (int)source.size();
|
||||
const int size = MultiByteToWideChar(CP_UTF8, 0, source.data(), len, NULL, 0);
|
||||
std::wstring str;
|
||||
str.resize(size);
|
||||
if (size > 0) {
|
||||
@@ -58,6 +59,11 @@ void WASAPIContext::EnumerateDevices(std::vector<AudioDeviceDesc> *output, bool
|
||||
IMMDeviceCollection *collection = nullptr;
|
||||
enumerator_->EnumAudioEndpoints(captureDevices ? eCapture : eRender, DEVICE_STATE_ACTIVE, &collection);
|
||||
|
||||
if (!collection) {
|
||||
ERROR_LOG(Log::Audio, "Failed to enumerate devices");
|
||||
return;
|
||||
}
|
||||
|
||||
UINT count = 0;
|
||||
collection->GetCount(&count);
|
||||
|
||||
@@ -124,7 +130,7 @@ bool WASAPIContext::InitOutputDevice(std::string_view uniqueId, LatencyMode late
|
||||
audioClient3_->GetMixFormat(&format_);
|
||||
audioClient3_->GetSharedModeEnginePeriod(format_, &defaultPeriodFrames, &fundamentalPeriodFrames, &minPeriodFrames, &maxPeriodFrames);
|
||||
|
||||
printf("default: %d fundamental: %d min: %d max: %d\n", defaultPeriodFrames, fundamentalPeriodFrames, minPeriodFrames, maxPeriodFrames);
|
||||
printf("default: %d fundamental: %d min: %d max: %d\n", (int)defaultPeriodFrames, (int)fundamentalPeriodFrames, (int)minPeriodFrames, (int)maxPeriodFrames);
|
||||
printf("initializing with %d frame period at %d Hz, meaning %0.1fms\n", (int)minPeriodFrames, (int)format_->nSamplesPerSec, FramesToMs(minPeriodFrames, format_->nSamplesPerSec));
|
||||
|
||||
audioEvent_ = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
@@ -218,7 +224,7 @@ void WASAPIContext::FrameUpdate(bool allowAutoChange) {
|
||||
|
||||
void WASAPIContext::AudioLoop() {
|
||||
DWORD taskID = 0;
|
||||
HANDLE mmcssHandle = NULL;
|
||||
HANDLE mmcssHandle = nullptr;
|
||||
if (latencyMode_ == LatencyMode::Aggressive) {
|
||||
mmcssHandle = AvSetMmThreadCharacteristics(L"Pro Audio", &taskID);
|
||||
}
|
||||
@@ -244,7 +250,7 @@ void WASAPIContext::AudioLoop() {
|
||||
else
|
||||
audioClient_->GetCurrentPadding(&padding), audioClient_->GetBufferSize(&available);
|
||||
|
||||
UINT32 framesToWrite = available - padding;
|
||||
const UINT32 framesToWrite = available - padding;
|
||||
BYTE* buffer = nullptr;
|
||||
if (framesToWrite > 0 && SUCCEEDED(renderClient_->GetBuffer(framesToWrite, &buffer))) {
|
||||
callback_((float *)buffer, framesToWrite, 2, format_->nSamplesPerSec, userdata_);
|
||||
|
||||
+10
-11
@@ -19,7 +19,7 @@ static volatile BOOL done = 0;
|
||||
#define SAMPLE_SIZE 44100
|
||||
static short stream[SAMPLE_SIZE];
|
||||
|
||||
int NativeMix(short *audio, int numSamples, int sampleRateHz, void *userdata);
|
||||
void NativeMix(short *audio, int numSamples, int sampleRateHz, void *userdata);
|
||||
|
||||
@interface AudioEngine ()
|
||||
|
||||
@@ -121,16 +121,15 @@ int NativeMix(short *audio, int numSamples, int sampleRateHz, void *userdata);
|
||||
{
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
|
||||
const int sampleRateHz = 44100;
|
||||
while (!done)
|
||||
{
|
||||
size_t frames_ready;
|
||||
if (![self playing])
|
||||
frames_ready = NativeMix(stream, SAMPLE_SIZE / 2, sampleRateHz, 0);
|
||||
else
|
||||
while (!done) {
|
||||
if (![self playing]) {
|
||||
NativeMix(stream, SAMPLE_SIZE / 2, sampleRateHz, 0);
|
||||
frames_ready = SAMPLE_SIZE / 2;
|
||||
} else {
|
||||
frames_ready = 0;
|
||||
}
|
||||
|
||||
if (frames_ready > 0)
|
||||
{
|
||||
if (frames_ready > 0) {
|
||||
const size_t bytes_ready = frames_ready * sizeof(short) * 2;
|
||||
alSourcei(source, AL_BUFFER, 0);
|
||||
alBufferData(buffer, AL_FORMAT_STEREO16, stream, bytes_ready, sampleRateHz);
|
||||
@@ -139,9 +138,9 @@ int NativeMix(short *audio, int numSamples, int sampleRateHz, void *userdata);
|
||||
|
||||
// TODO: Maybe this could get behind?
|
||||
usleep((1000000 * frames_ready) / sampleRateHz);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
usleep(100);
|
||||
}
|
||||
pthread_yield_np();
|
||||
}
|
||||
});
|
||||
|
||||
+5
-25
@@ -74,41 +74,21 @@ void iOSCoreAudioSetDisplayConnected(bool connected) {
|
||||
iOSCoreAudioUpdateSession();
|
||||
}
|
||||
|
||||
int NativeMix(short *audio, int numSamples, int sampleRate, void *userdata);
|
||||
void NativeMix(short *audio, int numSamples, int sampleRate, void *userdata);
|
||||
|
||||
OSStatus iOSCoreAudioCallback(void *inRefCon,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList *ioData)
|
||||
{
|
||||
// see if we have any sound to play
|
||||
AudioBufferList *ioData) {
|
||||
short *output = (short *)ioData->mBuffers[0].mData;
|
||||
UInt32 framesReady = NativeMix(output, inNumberFrames, SAMPLE_RATE, nullptr);
|
||||
|
||||
if (framesReady == 0) {
|
||||
// oops, we don't currently have any sound, so return silence
|
||||
*ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
|
||||
}
|
||||
|
||||
/*
|
||||
* You'd think iOS would want to know how many frames were
|
||||
* actually generated in case it was less than asked for, but
|
||||
* apparently that causes micro-stuttering and everything just
|
||||
* works better if we lie and say we successfully generated as
|
||||
* many frames as it wanted... weird. We still get micro-stuttering
|
||||
* but it's less noticeable this way.
|
||||
*/
|
||||
//UInt32 bytesReady = framesReady * sizeof(short) * 2;
|
||||
UInt32 bytesReady = inNumberFrames * sizeof(short) * 2;
|
||||
ioData->mBuffers[0].mDataByteSize = bytesReady;
|
||||
|
||||
NativeMix(output, inNumberFrames, SAMPLE_RATE, nullptr);
|
||||
ioData->mBuffers[0].mDataByteSize = inNumberFrames * sizeof(short) * 2;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void iOSCoreAudioInit()
|
||||
{
|
||||
void iOSCoreAudioInit() {
|
||||
iOSCoreAudioUpdateSession();
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
Reference in new issue
Block a user