Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
6278746
Suggest the default low latency
sakertooth Aug 11, 2024
c3902ce
Remove verbose comments
sakertooth Aug 11, 2024
0e51917
Completely remove old PortAudio < v19 code
sakertooth Aug 11, 2024
916aa1f
Remove redundant header guard
sakertooth Aug 11, 2024
dc5b01c
Rename and move setup widget into gui namespace
sakertooth Aug 11, 2024
0a3fcd1
Fix naming of callback functions
sakertooth Aug 11, 2024
b66a281
Merge AudioPortAudioSetupWidget and AudioPortAudioSetupUtil
sakertooth Aug 11, 2024
53cbe47
Fix naming in constructor
sakertooth Aug 11, 2024
fbdb591
Fix naming for parameters of callback functions
sakertooth Aug 11, 2024
9af62b0
Move closing brace up
sakertooth Aug 11, 2024
df2af4d
Clean up constructor
sakertooth Aug 11, 2024
2258eb7
Replace printf calls on error with std::cerr
sakertooth Aug 11, 2024
88949fc
Use unique_ptr for m_outBuf
sakertooth Aug 11, 2024
501056b
Do not use multiple techniques to start and stop the stream
sakertooth Aug 12, 2024
3f5ce10
Move back to using paComplete
sakertooth Aug 12, 2024
3cc20ee
Fix naming style
sakertooth Aug 12, 2024
4c8ba0d
Replace memset with std::fill_n
sakertooth Aug 12, 2024
0e51ae1
Remove redundant frames variable
sakertooth Aug 12, 2024
6f27d17
Simplify nested for loop
sakertooth Aug 12, 2024
44d0ca9
Fix unsigned comparison
sakertooth Aug 12, 2024
22442ef
Use Qt's combo boxes
sakertooth Aug 12, 2024
cb1bbe0
Include memory header
sakertooth Aug 12, 2024
e115ed3
Remove LcdSpinBox forward declaration
sakertooth Aug 12, 2024
e205701
Stop searching for devices when the correct device is found
sakertooth Jan 15, 2025
ee1716b
Fix formatting
sakertooth Jan 15, 2025
b7def39
Set suggestedLatency to the correct values
sakertooth Jan 15, 2025
bb085cc
Stop clamping channel count to 2
sakertooth Jan 16, 2025
6c87246
Use default number of channels when no amount is specified in the config
sakertooth Jan 18, 2025
8be5793
Simplify construction logic
sakertooth Jan 27, 2025
a5a0c02
Use QString::number instead of trying to construct string from number
sakertooth Jan 27, 2025
e7ae83c
Stop calculating latency twice
sakertooth Jan 27, 2025
9039b5d
Add whitespace
sakertooth Jan 27, 2025
d98c166
Remove input device
sakertooth Jan 27, 2025
f19fc65
Apply adjustments
sakertooth Jan 30, 2025
222c601
Update devices when backend changes
sakertooth Jan 30, 2025
3d805da
Add PortAudio initialization RAII guard
sakertooth Jan 30, 2025
e72bfec
Improve backend, device, and channel finding and selection logic
sakertooth Jan 31, 2025
cc1a14d
Early return when no backend or device is selected, update both devic…
sakertooth Jan 31, 2025
e001a9c
Set sample rate and channel count lazily
sakertooth Jan 31, 2025
8bdc051
Support downmixing to mono
sakertooth Jan 31, 2025
6ebccb2
Remove anonymous namespace
sakertooth Jan 31, 2025
be901c5
Fix audio processing to work with any number of channels
sakertooth Jan 31, 2025
9221724
Fix audio glitches when playing wiith buffer sizes other than 256
sakertooth Feb 4, 2025
78e49c3
Set sample rate and channel count even on failure to open device
sakertooth Feb 4, 2025
90402f7
Make adjustment
sakertooth Feb 4, 2025
deee77a
Check for errors in PortAudioInitializationGuard
sakertooth Feb 9, 2025
80257ba
PortAudioInitializationGuard: Print error message in the constructor
sakertooth Feb 9, 2025
b50e385
Simplify/fix callback processing
sakertooth Feb 16, 2025
7d8b058
Update backend, devices, and channel count without early returns
sakertooth Feb 16, 2025
161d756
Fix formatting
sakertooth Feb 16, 2025
aee24f9
More formatting
sakertooth Feb 16, 2025
f091077
Remove use of Q_UNUSED
sakertooth Feb 17, 2025
b7b0489
Simplify starting and stopping stream
sakertooth Feb 17, 2025
2b721a4
Close stream on call to destructor
sakertooth Feb 17, 2025
7c1e089
Check for errors when terminating PortAudio
sakertooth Feb 17, 2025
7dc0f62
Check if PortAudio format is supported
sakertooth Feb 17, 2025
ac0819f
Fix invalid stream pointer error when closing the stream
sakertooth Feb 17, 2025
8064086
Print more diagnostics
sakertooth Feb 17, 2025
60d3282
Print out even more diagnostics
sakertooth Feb 17, 2025
c212bd8
Iterate the devices with the associated host API instead of all avail…
sakertooth Feb 17, 2025
2bf8504
Update channel count in the config
sakertooth Feb 17, 2025
cab5d57
Change order
sakertooth Feb 17, 2025
1fb3fde
Skip backends and devices when enumerating where possible
sakertooth Feb 17, 2025
6ae01ea
Start over
sakertooth Feb 28, 2025
00d0bd6
Improve naming, fix crash
sakertooth Feb 28, 2025
49b868e
Remove error handling when starting and stopping stream
sakertooth Feb 28, 2025
f54f483
Simplify callback declaration
sakertooth Feb 28, 2025
7f73b81
Add UI elements
sakertooth Feb 28, 2025
7c7e234
Implement functionality to fill in UI elements
sakertooth Feb 28, 2025
d13d1a4
Implement updating channels
sakertooth Feb 28, 2025
8a24685
Set the number of channels after opening stream
sakertooth Feb 28, 2025
1fee7a6
Make error handling more descriptive
sakertooth Feb 28, 2025
d58a271
Use only single backend
sakertooth Feb 28, 2025
561ec57
Simplify scope
sakertooth Mar 1, 2025
a1f18f9
Fix layout
sakertooth Mar 1, 2025
ebd1c7c
Set sampleRate and channel count after opening stream
sakertooth Mar 1, 2025
b8914c5
Refresh channel range when switching devices
sakertooth Mar 1, 2025
a47c8ac
Lazily initialize PortAudio
sakertooth Mar 1, 2025
4778130
Fix whitespace issues
sakertooth Mar 1, 2025
73f62e0
Rename DeviceSpecWidget to DeviceSelectorWidget
sakertooth Mar 1, 2025
56a1fe6
Stop storing direction (input/output) and remove DeviceSpec
sakertooth Mar 1, 2025
251d9ac
Add numChannelsFromConfig function
sakertooth Mar 1, 2025
dc189eb
Fix issues
sakertooth Mar 1, 2025
91c5085
Fix formatting
sakertooth Mar 1, 2025
8307146
Make stream parameters const
sakertooth Mar 1, 2025
1d28ff7
Fix mono playback regression
sakertooth Mar 2, 2025
c1646bb
Add RAII guard for initializing PortAudio
sakertooth Mar 2, 2025
03d6b79
Fix code quality warnings
sakertooth Mar 3, 2025
5cfd0d6
Merge remote-tracking branch 'upstream' into cleanup-portaudio-backend
sakertooth Mar 25, 2025
92bee19
Merge remote-tracking branch 'upstream' into cleanup-portaudio-backend
sakertooth Mar 25, 2025
c3c4fdc
Try the chosen sample rate + any other supported sample rates when st…
sakertooth Mar 25, 2025
c6724f6
Do not set the channel count in the config
sakertooth Mar 25, 2025
a1c3dae
Check for errors when opening, starting, stopping, or closing stream
sakertooth Mar 25, 2025
b52933d
Only fill buffer with zeros when necessary
sakertooth Mar 31, 2025
2397ca1
Add support for choosing bit depth, simplify device construction
sakertooth Apr 7, 2025
07c4dc9
Remove bit depth option
sakertooth Apr 9, 2025
a8bdc5e
Check if format is supported
sakertooth Apr 9, 2025
95e19c1
Pass in correct input and output parameters when opening stream
sakertooth Apr 9, 2025
741554e
Print PortAudio version
sakertooth Apr 9, 2025
8db77fc
Our PortAudio on Windows is old, so use deprecated function
sakertooth Apr 9, 2025
3bc7c9c
Merge remote-tracking branch 'upstream' into cleanup-portaudio-backend
sakertooth Jul 21, 2025
73ab85e
Merge remote-tracking branch 'upstream' into cleanup-portaudio-backend
sakertooth Jul 21, 2025
7c46784
Use default low output latency
sakertooth Jul 21, 2025
6d94157
Remove default device fallback
sakertooth Jul 21, 2025
8c1115b
Rewrite construction code
sakertooth Sep 16, 2025
e3a0040
Remove print calls
sakertooth Sep 17, 2025
c075d55
Remove Direction parameter from DeviceSelectorWidget
sakertooth Sep 17, 2025
afd1fb0
Remove unused iostream inclusion
sakertooth Sep 17, 2025
2b9cd5b
Remove numChannelsFromConfig function
sakertooth Sep 17, 2025
b101cc7
Combine duplicate for loop
sakertooth Sep 17, 2025
8165051
Use sampleRate instead of engine->baseSampleRate
sakertooth Sep 17, 2025
7fa3712
Add popup message to adjust settings when failing to setup an audio d…
sakertooth Sep 17, 2025
7a74562
Merge branch 'master' into cleanup-portaudio-backend
sakertooth Sep 17, 2025
2c543b9
Set output channels
sakertooth Sep 17, 2025
38becd1
Fix declaration order for constructions of PaStreamParameters
sakertooth Sep 17, 2025
4d3c6fb
Do not fail if certain parts of the config are missing
sakertooth Sep 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/AudioDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ class AudioDevice
m_sampleRate = _new_sr;
}

void setChannels(const ch_cnt_t channels)
{
m_channels = channels;
}

AudioEngine* audioEngine()
{
return m_audioEngine;
Expand Down
156 changes: 54 additions & 102 deletions include/AudioPortAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,136 +25,88 @@
#ifndef LMMS_AUDIO_PORTAUDIO_H
#define LMMS_AUDIO_PORTAUDIO_H

#include <QObject>

#include "lmmsconfig.h"
#include "ComboBoxModel.h"

#ifdef LMMS_HAVE_PORTAUDIO

# include <portaudio.h>

# include "AudioDevice.h"
# include "AudioDeviceSetupWidget.h"

# if defined paNeverDropInput || defined paNonInterleaved
# define PORTAUDIO_V19
# else
# define PORTAUDIO_V18
# endif
#include <QComboBox>
#include <QFormLayout>
#include <QString>
#include <QWidget>
#include <portaudio.h>

#endif


namespace lmms
{
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"

class AudioPortAudioSetupUtil : public QObject
namespace lmms {
class PortAudioInitializationGuard
{
Q_OBJECT
public slots:
void updateBackends();
void updateDevices();
void updateChannels();

public:
ComboBoxModel m_backendModel;
ComboBoxModel m_deviceModel;
};


#ifdef LMMS_HAVE_PORTAUDIO
PortAudioInitializationGuard()
: m_error(Pa_Initialize())
{
if (m_error != paNoError) { throw std::runtime_error{"PortAudio: could not initialize"}; }
}

~PortAudioInitializationGuard()
{
if (m_error == paNoError) { Pa_Terminate(); }
}

namespace gui
{
class ComboBox;
}
PortAudioInitializationGuard(const PortAudioInitializationGuard&) = default;
PortAudioInitializationGuard(PortAudioInitializationGuard&&) = delete;
PortAudioInitializationGuard& operator=(const PortAudioInitializationGuard&) = default;
PortAudioInitializationGuard& operator=(PortAudioInitializationGuard&&) = delete;

private:
PaError m_error = paNoError;
};

class AudioPortAudio : public AudioDevice
{
public:
AudioPortAudio( bool & _success_ful, AudioEngine* audioEngine );
AudioPortAudio(bool& successful, AudioEngine* engine);
~AudioPortAudio() override;

inline static QString name()
{
return QT_TRANSLATE_NOOP( "AudioDeviceSetupWidget", "PortAudio" );
}
AudioPortAudio(const AudioPortAudio&) = delete;
AudioPortAudio(AudioPortAudio&&) = delete;
AudioPortAudio& operator=(const AudioPortAudio&) = delete;
AudioPortAudio& operator=(AudioPortAudio&&) = delete;

int process_callback(const float* _inputBuffer, float* _outputBuffer, f_cnt_t _framesPerBuffer);

class setupWidget : public gui::AudioDeviceSetupWidget
{
public:
setupWidget( QWidget * _parent );
~setupWidget() override;

void saveSettings() override;
void show() override;

private:
gui::ComboBox * m_backend;
gui::ComboBox * m_device;
AudioPortAudioSetupUtil m_setupUtil;

} ;

private:
void startProcessing() override;
void stopProcessing() override;

#ifdef PORTAUDIO_V19
static int _process_callback( const void *_inputBuffer, void * _outputBuffer,
unsigned long _framesPerBuffer,
const PaStreamCallbackTimeInfo * _timeInfo,
PaStreamCallbackFlags _statusFlags,
void *arg );

#else
static auto name() -> QString { return QT_TRANSLATE_NOOP("AudioDeviceSetupWidget", "PortAudio"); }

#define paContinue 0
#define paComplete 1
#define Pa_GetDeviceCount Pa_CountDevices
#define Pa_GetDefaultInputDevice Pa_GetDefaultInputDeviceID
#define Pa_GetDefaultOutputDevice Pa_GetDefaultOutputDeviceID
#define Pa_IsStreamActive Pa_StreamActive

static int _process_callback( void * _inputBuffer, void * _outputBuffer,
unsigned long _framesPerBuffer, PaTimestamp _outTime, void * _arg );


using PaTime = double;
using PaDeviceIndex = PaDeviceID;

using PaStreamParameters = struct
{
PaDeviceIndex device;
int channelCount;
PaSampleFormat sampleFormat;
PaTime suggestedLatency;
void *hostApiSpecificStreamInfo;

} PaStreamParameters;
#endif // PORTAUDIO_V19
private:
static int processCallback(const void* input, void* output, unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData);

PaStream * m_paStream;
PaStreamParameters m_outputParameters;
PaStreamParameters m_inputParameters;
PortAudioInitializationGuard m_initGuard;

bool m_wasPAInitError;
PaStream* m_paStream = nullptr;
std::vector<SampleFrame> m_outBuf;
std::size_t m_outBufPos = 0;
};
} // namespace lmms

SampleFrame* m_outBuf;
std::size_t m_outBufPos;
fpp_t m_outBufSize;
namespace lmms::gui {
class AudioPortAudioSetupWidget : public AudioDeviceSetupWidget
{
public:
AudioPortAudioSetupWidget(QWidget* parent);

bool m_stopped;
void show() override;
void saveSettings() override;

} ;
private:
class DeviceSelectorWidget;
QComboBox* m_backendComboBox = nullptr;
DeviceSelectorWidget* m_inputDevice = nullptr;
DeviceSelectorWidget* m_outputDevice = nullptr;
};
} // namespace lmms::gui

#endif // LMMS_HAVE_PORTAUDIO

} // namespace lmms

#endif // LMMS_AUDIO_PORTAUDIO_H
3 changes: 2 additions & 1 deletion src/core/AudioEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/

#include "AudioEngine.h"
#include <iostream>

#include "MixHelpers.h"
#include "denormals.h"
Expand Down Expand Up @@ -906,7 +907,7 @@ AudioDevice * AudioEngine::tryAudioDevices()


#ifdef LMMS_HAVE_PORTAUDIO
if( dev_name == AudioPortAudio::name() || dev_name == "" )
if ( dev_name == AudioPortAudio::name() || dev_name == "" )
{
dev = new AudioPortAudio( success_ful, this );
if( success_ful )
Expand Down
Loading
Loading