WIP Edits
This commit is contained in:
@@ -38,9 +38,7 @@ endif()
|
|||||||
|
|
||||||
include_directories("include")
|
include_directories("include")
|
||||||
|
|
||||||
add_library(ReMixer ${SOURCES}
|
add_library(ReMixer ${SOURCES})
|
||||||
src/linux/PulseSubsystem.cpp
|
|
||||||
src/linux/SoundSubsystem.cpp)
|
|
||||||
|
|
||||||
add_executable(ReMixer-Test main.cpp)
|
add_executable(ReMixer-Test main.cpp)
|
||||||
|
|
||||||
@@ -65,7 +63,7 @@ target_link_libraries(ReMixer-Test PUBLIC ReMixer)
|
|||||||
|
|
||||||
add_executable(pacat pacat_simple.cpp
|
add_executable(pacat pacat_simple.cpp
|
||||||
src/windows/ReMixer.cpp
|
src/windows/ReMixer.cpp
|
||||||
include/ReMixer/PulseSubsystem.h)
|
include/ReMixer/PulseDevice.h)
|
||||||
target_link_libraries(pacat pulse-simple pulse)
|
target_link_libraries(pacat pulse-simple pulse)
|
||||||
|
|
||||||
add_executable(vorbis_decode vorbis_decode.cpp)
|
add_executable(vorbis_decode vorbis_decode.cpp)
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "AudioFormat.hpp"
|
||||||
#include "ReMixer.h"
|
#include "ReMixer.h"
|
||||||
|
|
||||||
namespace ReMixer {
|
namespace ReMixer {
|
||||||
@@ -15,6 +16,12 @@ namespace ReMixer {
|
|||||||
std::set<AudioFormat> supported_formats;
|
std::set<AudioFormat> supported_formats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IAudioDevice;
|
||||||
|
|
||||||
|
using PlaybackCallback = std::;
|
||||||
|
using CaptureCallback = 0;
|
||||||
|
using DeviceStateCallback = 0;
|
||||||
|
|
||||||
class IAudioDevice {
|
class IAudioDevice {
|
||||||
public:
|
public:
|
||||||
virtual ~IAudioDevice() = default;
|
virtual ~IAudioDevice() = default;
|
||||||
@@ -25,6 +32,15 @@ namespace ReMixer {
|
|||||||
virtual bool Stop() = 0;
|
virtual bool Stop() = 0;
|
||||||
virtual bool IsRunning() const = 0;
|
virtual bool IsRunning() const = 0;
|
||||||
|
|
||||||
|
virtual AudioDeviceInfo GetInfo() const = 0;
|
||||||
|
virtual AudioFormat GetActualFormat() const = 0;
|
||||||
|
virtual uint32_t GetActualBufferSizeFrames() const = 0;
|
||||||
|
virtual double GetLatencyMilliseconds() const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* AsPlatformSpecific() { return dynamic_cast<T>(*this); }
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,20 @@
|
|||||||
|
|
||||||
namespace ReMixer
|
namespace ReMixer
|
||||||
{
|
{
|
||||||
|
namespace PulseAudio {
|
||||||
|
class PulseDevice : public IAudioDevice {
|
||||||
|
public:
|
||||||
|
PulseDevice(const AudioDeviceInfo& info);
|
||||||
|
~PulseDevice() override;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// A PulseAudio implementation of the SoundSubsystem.
|
/// A PulseAudio implementation of the SoundSubsystem.
|
||||||
class PulseAudioSubsystem : public SoundSubsystem
|
class PulseAudioSubsystem : public SoundSubsystem
|
||||||
{
|
{
|
@@ -7,137 +7,42 @@
|
|||||||
|
|
||||||
namespace ReMixer {
|
namespace ReMixer {
|
||||||
|
|
||||||
/// 1. Abstraction Layer:
|
/// TODO: Support JACK
|
||||||
/// Define abstract base classes or interfaces that capture the common
|
/// TOOD: Support ALSA
|
||||||
/// functionalities across all supported audio APIs.
|
/// TODO: Support PulseAudio
|
||||||
/// 2. Platform Specific Implementations:
|
/// TODO: Support WASAPI
|
||||||
/// Create conrete classes for each platform (PulseDevice, WasapiDevice)
|
|
||||||
/// that inherit from the abstract interfaces and implement the API-specific calls.
|
|
||||||
/// 3. Factory Pattern:
|
|
||||||
/// Use a factory function or class to create the correct platform-specific
|
|
||||||
/// implementation at runtime, based on the operating system.
|
|
||||||
/// 4. Resource Management:
|
|
||||||
/// Employ RAII for managing audio device handles, streams, and buffers. Utilize Smart Pointers?
|
|
||||||
/// 5. Callbacks for asynchronous operations:
|
|
||||||
/// Most low-level audio APIs use callbacks for delivering audio data (playback/capture)
|
|
||||||
/// or notifying of device state changes. Your wrapper classes should expose this through
|
|
||||||
/// C++ lambdas or std::function (or josh/Event)
|
|
||||||
/// 6. Error Handling:
|
|
||||||
/// A consistent error reporting mechanism is crucial
|
|
||||||
/// 7. Data Formats:
|
|
||||||
/// Handle common audio formats (PCM float, int16, int32) and sample rates. Provide conversion utilities if necessary.
|
|
||||||
/// 8. Device Enumeration:
|
|
||||||
/// Allow users to discover available audio input and output devices.
|
|
||||||
///
|
|
||||||
|
|
||||||
enum class SampleFormat {
|
|
||||||
Unknown,
|
|
||||||
Float16,
|
|
||||||
Float32,
|
|
||||||
Int16,
|
|
||||||
Int32,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned operator ""_Hz(unsigned long long int frequency);
|
|
||||||
unsigned operator ""_kHz(long double frequency);
|
|
||||||
unsigned operator ""_kHz(unsigned long long int frequency);
|
|
||||||
|
|
||||||
struct AudioFormat {
|
|
||||||
uint32_t sample_rate;
|
|
||||||
uint16_t channels;
|
|
||||||
SampleFormat format;
|
|
||||||
|
|
||||||
static AudioFormat StereoFloat(uint32_t rate) {
|
|
||||||
return {rate, 2, SampleFormat::Float16};
|
|
||||||
}
|
|
||||||
|
|
||||||
static AudioFormat StereoFloat48kHz() {
|
|
||||||
return StereoFloat(48_kHz);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum class DeviceType {
|
// TODO: Support Recording
|
||||||
Unknown, Output, Input, Duplex
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AudioDeviceInfo {
|
|
||||||
std::string id;
|
|
||||||
std::string name;
|
|
||||||
DeviceType type;
|
|
||||||
bool is_default;
|
|
||||||
std::set<AudioFormat> supported_formats;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Sound;
|
class Sound;
|
||||||
|
class SoundHandle;
|
||||||
|
|
||||||
|
class IAudioDevice;
|
||||||
|
|
||||||
class Stream;
|
class Stream;
|
||||||
class SoundSubsystem;
|
class SoundSubsystem;
|
||||||
class PulseAudioSubsystem;
|
class PulseAudioSubsystem;
|
||||||
class PulseStream;
|
class PulseStream;
|
||||||
|
|
||||||
enum class PlaybackStatus { Stopped, Playing, Paused, Finished, Error };
|
|
||||||
|
|
||||||
class SoundHandle {
|
|
||||||
friend void Init();
|
|
||||||
friend SoundHandle* PlaySoundAsync(Sound& sound);
|
|
||||||
public:
|
|
||||||
|
|
||||||
Event<> Finished;
|
|
||||||
Event<> Paused;
|
|
||||||
Event<std::string> ErrorEncountered;
|
|
||||||
|
|
||||||
|
|
||||||
void Pause();
|
|
||||||
void Resume();
|
|
||||||
void Stop();
|
|
||||||
|
|
||||||
PlaybackStatus Status() const;
|
|
||||||
bool IsPlaying() const;
|
|
||||||
bool IsPaused() const;
|
|
||||||
bool IsStopped();
|
|
||||||
float GetPlaybackPositionMs() const;
|
|
||||||
float GetPlaybackPositionPercent() const;
|
|
||||||
|
|
||||||
/// Playback speed control (e.g., 0.5 for half speed, 2.0 for double speed)
|
|
||||||
/// @note Requires sample rate conversion or similar at lower level.
|
|
||||||
void SetPlaybackSpeed(float rate);
|
|
||||||
float GetPlaybackSpeed() const;
|
|
||||||
|
|
||||||
void SetPlaybackPositionMs(float ms);
|
|
||||||
void SetPlaybackPositionPercent(float percent);
|
|
||||||
void Seek(float ms);
|
|
||||||
void SeekPercent(float percent);
|
|
||||||
|
|
||||||
/// Volume control (0.0 to 1.0)
|
|
||||||
void SetVolume(float volume);
|
|
||||||
float GetVolume() const;
|
|
||||||
protected:
|
|
||||||
SoundHandle(const Sound& sound);
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
class IAudioDevice {
|
|
||||||
public:
|
|
||||||
virtual ~IAudioDevice() = default;
|
|
||||||
|
|
||||||
virtual bool Initialize(const AudioFormat& requestedFormat, uint32_t bufferSizeFrames) = 0;
|
|
||||||
virtual void Shutdown() = 0;
|
|
||||||
virtual bool Start() = 0;
|
|
||||||
virtual bool Stop() = 0;
|
|
||||||
virtual bool IsRunning() const = 0;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
|
#pragma region Simple API
|
||||||
/// Simple high-level API for sound playback.
|
/// Simple high-level API for sound playback.
|
||||||
/// @note Assumes you want the default device, and ideal parameters to properly play the sound.
|
/// @note Assumes you want the default device, and ideal parameters to properly play the sound.
|
||||||
/// @return SoundHandle instance for managing the state of playback. (i.e. pause, seek, resume, playback speed, events.)
|
/// @return SoundHandle instance for managing the state of playback. (i.e. pause, seek, resume, playback speed, events.)
|
||||||
SoundHandle* PlaySoundAsync(Sound& Sound);
|
SoundHandle* PlaySoundAsync(Sound& Sound);
|
||||||
|
std::vector<IAudioDevice*> EnumerateDevices();
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Advanced API
|
||||||
|
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "AudioFormat.hpp"
|
||||||
|
|
||||||
int mix(int a, int b);
|
int mix(int a, int b);
|
||||||
|
|
||||||
namespace ReMixer {
|
namespace ReMixer {
|
||||||
|
8
include/ReMixer/WasapiDevice.hpp
Normal file
8
include/ReMixer/WasapiDevice.hpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
//
|
||||||
|
// Created by josh on 7/16/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef WASAPIDEVICE_HPP
|
||||||
|
#define WASAPIDEVICE_HPP
|
||||||
|
|
||||||
|
#endif //WASAPIDEVICE_HPP
|
5
main.cpp
5
main.cpp
@@ -16,13 +16,16 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <ReMixer/stream.h>
|
#include <ReMixer/stream.h>
|
||||||
#include <ReMixer/Sound.hpp>
|
#include <ReMixer/Sound.hpp>
|
||||||
#include <ReMixer/PulseSubsystem.h>
|
#include <ReMixer/PulseDevice.h>
|
||||||
#include <ReMixer/ReMixer.h>
|
#include <ReMixer/ReMixer.h>
|
||||||
|
|
||||||
|
#include "ReMixer/Frequency.hpp"
|
||||||
|
|
||||||
[[noreturn]] int main() {
|
[[noreturn]] int main() {
|
||||||
|
|
||||||
using namespace ReMixer;
|
using namespace ReMixer;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
using namespace ReMixer::FrequencyLiterals;
|
||||||
|
|
||||||
uint measurement = 44.1_kHz;
|
uint measurement = 44.1_kHz;
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include <ReMixer/PulseSubsystem.h>
|
#include <ReMixer/PulseDevice.h>
|
||||||
|
|
||||||
void ReMixer::PulseAudioSubsystem::Play(ReMixer::PulseStream &stream, const ReMixer::Sound &sound) {
|
void ReMixer::PulseAudioSubsystem::Play(ReMixer::PulseStream &stream, const ReMixer::Sound &sound) {
|
||||||
|
|
Reference in New Issue
Block a user