From fde087c63d14b6eb40a5b1fc4095d847b59a7f34 Mon Sep 17 00:00:00 2001 From: pszsh Date: Sun, 25 Jan 2026 04:27:50 -0800 Subject: [PATCH] android fix --- .sdkmanrc | 4 +++ src/AudioEngine.cpp | 80 +++++++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 35 deletions(-) create mode 100644 .sdkmanrc diff --git a/.sdkmanrc b/.sdkmanrc new file mode 100644 index 0000000..ff24131 --- /dev/null +++ b/.sdkmanrc @@ -0,0 +1,4 @@ +# Enable auto-env through the sdkman_auto_env config +# Add key=value pairs of SDKs to use below +java=17-homebrew +gradle=9.2.1 \ No newline at end of file diff --git a/src/AudioEngine.cpp b/src/AudioEngine.cpp index 74e7b50..0f9c962 100644 --- a/src/AudioEngine.cpp +++ b/src/AudioEngine.cpp @@ -1,3 +1,5 @@ +// src/AudioEngine.cpp + #include "AudioEngine.h" #include #include @@ -7,6 +9,7 @@ #include #include #include +#include AudioEngine::AudioEngine(QObject* parent) : QObject(parent) { m_processors.push_back(new Processor(m_frameSize, m_sampleRate)); @@ -60,7 +63,6 @@ void AudioEngine::loadTrack(const QString& filePath) { } else { delete m_fileSource; m_fileSource = nullptr; - // Fix: Handle content:// URIs correctly if (filePath.startsWith("content://")) { m_decoder->setSource(QUrl(filePath)); } else { @@ -83,38 +85,18 @@ void AudioEngine::onBufferReady() { QAudioBuffer buffer = m_decoder->read(); if (!buffer.isValid()) return; - // Fix: Explicit cast to int to avoid warning const int frames = static_cast(buffer.frameCount()); const int channels = buffer.format().channelCount(); auto sampleType = buffer.format().sampleFormat(); + // We store everything as Stereo Int16 to ensure compatibility with all sinks if (sampleType == QAudioFormat::Int16) { const int16_t* src = buffer.constData(); if (!src) return; for (int i = 0; i < frames; ++i) { - float left = 0.0f; - float right = 0.0f; - - if (channels == 1) { - left = src[i] / 32768.0f; - right = left; - } else if (channels >= 2) { - left = src[i * channels] / 32768.0f; - right = src[i * channels + 1] / 32768.0f; - } - - m_pcmData.append(reinterpret_cast(&left), sizeof(float)); - m_pcmData.append(reinterpret_cast(&right), sizeof(float)); - } - } - else if (sampleType == QAudioFormat::Float) { - const float* src = buffer.constData(); - if (!src) return; - - for (int i = 0; i < frames; ++i) { - float left = 0.0f; - float right = 0.0f; + int16_t left = 0; + int16_t right = 0; if (channels == 1) { left = src[i]; @@ -124,8 +106,35 @@ void AudioEngine::onBufferReady() { right = src[i * channels + 1]; } - m_pcmData.append(reinterpret_cast(&left), sizeof(float)); - m_pcmData.append(reinterpret_cast(&right), sizeof(float)); + m_pcmData.append(reinterpret_cast(&left), sizeof(int16_t)); + m_pcmData.append(reinterpret_cast(&right), sizeof(int16_t)); + } + } + else if (sampleType == QAudioFormat::Float) { + const float* src = buffer.constData(); + if (!src) return; + + auto toInt16 = [](float x) -> int16_t { + return static_cast(std::clamp(x, -1.0f, 1.0f) * 32767.0f); + }; + + for (int i = 0; i < frames; ++i) { + float l = 0.0f; + float r = 0.0f; + + if (channels == 1) { + l = src[i]; + r = l; + } else if (channels >= 2) { + l = src[i * channels]; + r = src[i * channels + 1]; + } + + int16_t left = toInt16(l); + int16_t right = toInt16(r); + + m_pcmData.append(reinterpret_cast(&left), sizeof(int16_t)); + m_pcmData.append(reinterpret_cast(&right), sizeof(int16_t)); } } } @@ -155,7 +164,7 @@ void AudioEngine::play() { QAudioFormat format; format.setSampleRate(44100); format.setChannelCount(2); - format.setSampleFormat(QAudioFormat::Float); + format.setSampleFormat(QAudioFormat::Int16); // Universal format QAudioDevice device = QMediaDevices::defaultAudioOutput(); if (device.isNull()) { @@ -164,13 +173,12 @@ void AudioEngine::play() { } if (!device.isFormatSupported(format)) { - qWarning() << "AudioEngine: Float format not supported, using preferred format."; + qWarning() << "AudioEngine: Int16 format not supported, using preferred format."; format = device.preferredFormat(); } m_sink = new QAudioSink(device, format, this); - connect(m_sink, &QAudioSink::stateChanged, this, [this](QAudio::State state){ if (state == QAudio::IdleState && m_sink->error() == QAudio::NoError) { if (m_buffer.bytesAvailable() == 0) { @@ -201,7 +209,8 @@ void AudioEngine::stop() { void AudioEngine::seek(float position) { if (m_pcmData.isEmpty()) return; qint64 pos = position * m_pcmData.size(); - pos -= pos % 8; + // Align to 4 bytes (2 channels * 2 bytes per sample) + pos -= pos % 4; if (m_buffer.isOpen()) m_buffer.seek(pos); } @@ -217,16 +226,17 @@ void AudioEngine::onProcessTimer() { qint64 currentPos = m_buffer.pos(); emit positionChanged((float)currentPos / m_pcmData.size()); - const float* samples = reinterpret_cast(m_pcmData.constData()); - qint64 sampleIdx = currentPos / sizeof(float); - qint64 totalSamples = m_pcmData.size() / sizeof(float); + // Convert Int16 back to Float for DSP + const int16_t* samples = reinterpret_cast(m_pcmData.constData()); + qint64 sampleIdx = currentPos / sizeof(int16_t); + qint64 totalSamples = m_pcmData.size() / sizeof(int16_t); if (sampleIdx + m_frameSize * 2 >= totalSamples) return; std::vector ch0(m_frameSize), ch1(m_frameSize); for (int i = 0; i < m_frameSize; ++i) { - ch0[i] = samples[sampleIdx + i*2]; - ch1[i] = samples[sampleIdx + i*2 + 1]; + ch0[i] = samples[sampleIdx + i*2] / 32768.0f; + ch1[i] = samples[sampleIdx + i*2 + 1] / 32768.0f; } m_processors[0]->pushData(ch0);