Compare commits

2 Commits
main ... Edits

Author SHA1 Message Date
9e214f3ab5 Slow progress on this laptop. 2025-07-22 13:59:00 -05:00
e1ff9f229b Buncha Edits 2025-07-19 05:09:09 -05:00
23 changed files with 147 additions and 152 deletions

View File

@@ -63,7 +63,7 @@ target_link_libraries(ReMixer-Test PUBLIC ReMixer)
add_executable(pacat pacat_simple.cpp
src/windows/ReMixer.cpp
include/ReMixer/PulseDevice.h)
include/ReMixer/PulseSubsystem.h)
target_link_libraries(pacat pulse-simple pulse)
add_executable(vorbis_decode vorbis_decode.cpp)

View File

@@ -0,0 +1,8 @@
//
// Created by dawsh on 7/18/25.
//
#ifndef ALSADEVICE_HPP
#define ALSADEVICE_HPP
#endif //ALSADEVICE_HPP

View File

@@ -0,0 +1,8 @@
//
// Created by dawsh on 7/18/25.
//
#ifndef JACKDEVICE_HPP
#define JACKDEVICE_HPP
#endif //JACKDEVICE_HPP

View File

@@ -8,6 +8,8 @@
/// @desc A PulseAudio implementation of the AudioSubsystem class.
/// @edit 2024-08-29
#pragma once
#include <pulse/pulseaudio.h>
#include <pulse/thread-mainloop.h>
#include <iostream>
@@ -16,22 +18,28 @@
#include <pulse/stream.h>
#include <pulse/introspect.h>
#pragma once
#include <ReMixer/SoundSubsystem.h>
#include <ReMixer/stream.h>
#include <format>
#include <map>
#include "ReMixer/IAudioDevice.hpp"
namespace ReMixer
{
namespace PulseAudio {
class PulseDevice : public IAudioDevice {
public:
PulseDevice(const AudioDeviceInfo& info);
PulseDevice(const AudioDeviceInfo& info, uint32_t buffer_size_frames);
~PulseDevice() override;
bool Initialize(const AudioFormat &requestedFormat, uint32_t bufferSizeFrames) override;
void Shutdown() override;
bool Start() override;
bool Stop() override;
bool IsRunning() const override;
void
};

View File

@@ -0,0 +1,8 @@
//
// Created by dawsh on 7/18/25.
//
#ifndef PULSESTREAM_HPP
#define PULSESTREAM_HPP
#endif //PULSESTREAM_HPP

View File

@@ -0,0 +1,21 @@
#pragma once
#include <ReMixer/IAudioDevice.hpp>
namespace ReMixer {
namespace Wasapi {
class WasapiDevice : public IAudioDevice {
public:
WasapiDevice(const AudioDeviceInfo& info);
~WasapiDevice();
bool Initialize(const AudioFormat& requested_format, uint32_t buffer_size_frames) override;
void Shutdown() override;
bool Start() override;
bool Stop() override;
bool IsRunning() const override;
SetPl
};
}
}

View File

@@ -0,0 +1,8 @@
//
// Created by dawsh on 7/18/25.
//
#ifndef WASAPISTREAM_HPP
#define WASAPISTREAM_HPP
#endif //WASAPISTREAM_HPP

View File

@@ -1,5 +1,5 @@
#pragma once
#include "AudioFormat.hpp"
#include <ReMixer/AudioFormat.hpp>
#include "ReMixer.h"
namespace ReMixer {
@@ -18,20 +18,48 @@ namespace ReMixer {
class IAudioDevice;
using PlaybackCallback = std::;
using CaptureCallback = 0;
using DeviceStateCallback = 0;
/// Playback callback: client fills the buffer with audio data.
/// @param outputBuffer (raw bytes)
/// @param framesToRender
/// @param userData (passed at initalization)
/// @return number of frames actually rendered. If less than framesToRender, indicates end of stream or underrun.
using PlaybackCallback = std::function<size_t(void* outputBuffer, uint32_t framesToRender, void* userData)>;
/// Capture callback: client receives audio data from the device.
/// @param inputBuffer (raw bytes)
/// @param framesCaptured
/// @param userData (passed at init)
/// @return void (or could return a status)
using CaptureCallback = std::function<void(void* outputBuffer, uint32_t framesToRender, void* userData)>;
/// Device state change callback (e.g. device unplugged, format changed).
/// Arguments: device, newStatus.
using DeviceStateCallback = std::function<void(IAudioDevice& device, bool isRunning)>; // Simplified for now.
/// Represents the physical or logical audio hardware device. It's responsible for managing the connection to the
/// underlying audio API, enumerating streams, and providing device-specific properties.
/// A single application might have one IAudioDevice instance per type (e.g. one default output device, on default input device).
/// @see IStream.hpp
class IAudioDevice {
public:
Event<> Connected;
Event<> Disconnected;
virtual ~IAudioDevice() = default;
virtual bool Initialize(const AudioFormat& requestedFormat, uint32_t bufferSizeFrames) = 0;
virtual void Shutdown() = 0;
virtual bool IsInitialized() const = 0;
virtual bool Start() = 0;
virtual bool Stop() = 0;
virtual bool IsRunning() const = 0;
virtual void SetPlaybackCallback(PlaybackCallback callback, void* user_data = nullptr) = 0;
virtual void SetCaptureCallback(CaptureCallback callback, void* user_data = nullptr);
virtual AudioDeviceInfo GetInfo() const = 0;
virtual AudioFormat GetActualFormat() const = 0;
virtual uint32_t GetActualBufferSizeFrames() const = 0;
@@ -42,5 +70,16 @@ namespace ReMixer {
T* AsPlatformSpecific() { return dynamic_cast<T>(*this); }
/// @param type indicates if it's a playback or capture stream.
/// @param requested_format is the desired format for this stream.
/// @param buffer_size_frames is the desired buffer size in frames for this stream.
/// @see struct AudioFormat.
virtual IStream* CreateStream(StreamDirection type, const AudioFormat& requested_format, uint32_t buffer_size_frames) = 0;
// Future: EnumerateStreams(), GetActiveStreams(), etc.
// Future: Device event callbacks (e.g. unplugged, device changed)
};
}

View File

@@ -4,7 +4,7 @@
/// (c) 2024 Redacted Software
/// This work is explicitly dedicated to the public domain, for the hopeful betterment of the software industry.
/// @file stream.h
/// @file IStream.hpp
/// @desc An audio stream class that interfaces with pulseaudio, etc, to play back sounds.
/// @edit 2024-08-06
@@ -32,6 +32,27 @@ namespace ReMixer {
STEREO = true
};
/// Represents an audio data pathway (e.g. a playback stream, a capture stream).
/// It's responsible for managing the actual flow of audio data to or from the device,
/// handling buffers, and callbacks. An IAudioDevice will create and manage IStream instances.
/// @see IAudioDevice.
class IStream {
public:
virtual ~IStream() = default;
virtual bool Initialize() = 0;
virtual void Shutdown() = 0;
virtual bool IsInitialized() const = 0;
virtual bool Start() = 0;
virtual bool Stop() = 0;
virtual bool IsRunning() const = 0;
virtual void SetPlaybackCallback(PlaybackCallback callback, void* userData = nullptr) = 0;
virtual void SetCaptureCallback(CaptureCallback callback, void* userData = nullptr) = 0;
};
/// The stream class is an abstract class that represents distinct output / input channels on an audio system.
/// Each audio system implements their concept of streams as a derivation of this class.
class Stream {

View File

@@ -2,11 +2,17 @@
#include <cstdint>
#include <set>
#include <string>
#include <Event.h>
#include <ReMixer/AudioFormat.hpp>
#include <ReMixer/Sound.hpp>
#include <ReMixer/SoundHandle.hpp>
#include <ReMixer/IAudioDevice.hpp>
#include "Sound.hpp"
namespace ReMixer {
/// TODO: Support JACK
/// TOOD: Support ALSA
/// TODO: Support PulseAudio

View File

@@ -9,12 +9,15 @@
/// @edit 2024-08-29
#pragma once
#include <vector>
#include <pulse/pulseaudio.h>
#include <pulse/simple.h>
#include <filesystem>
#include <ReMixer/stream.h>
#include <ReMixer/IStream.hpp>
#include <ReMixer/ReMixer.h>
#include <ReMixer/AudioFormat.hpp>
#include <iterator>
#include <vorbis/vorbisfile.h>
#include <algorithm>

View File

@@ -1,5 +1,5 @@
#pragma once
#include "sound.h"
#include <ReMixer/Sound.hpp>
namespace ReMixer {
class SoundHandle {

View File

@@ -1,75 +0,0 @@
#pragma once
#include <Event.h>
namespace ReMixer {
class Stream;
/// TODO: Equalizer Effect
/// TODO: Compressor Effect
/// TODO: Reverb Effect
/// TODO: Chorus Effect
/// TODO: Distortion Effect
/// TODO: Echo Effect
/// TODO: Flange Effect
/// TODO: Pitch Shift Effect
/// TODO: Tremolo Effect
/// TODO: Positional Sound Object?
/// Physical representation of Pulse-Code-Modulated sound data.
class PCM { };
class Decibels { };
enum class SoundApi
{
PulseAudio, /// Currently supported.
ALSA, /// Not yet supported.
PipeWire, /// Not yet supported.
WASAPI, /// Work-in-progress support.
OSS, /// Not yet supported.
CoreAudio /// Support not planned.
};
class AudioDevice {};
class PlaybackDevice : public AudioDevice {};
class RecordingDevice : public AudioDevice {};
/// An abstract class that defines the SoundSubsystem which will be used by the higher-level ReMixer API.
/// Since it is common for sound APIs to operate on a separate (or even multiple) threads,
/// The subsystem also functions as a "controller" that manages these separate threads.
/// Therefore, it is safe to use in a single-threaded application.
class SoundSubsystem
{
public:
SoundSubsystem() {}
std::vector<AudioDevice> GetAudioDevices();
std::vector<PlaybackDevice> GetPlaybackDevices();
std::vector<RecordingDevice> GetRecordingDevices();
std::string GetPlaybackDevice();
std::string GetRecordingDevice();
void SetPlaybackDevice();
void SetRecordingDevice();
void SetMasterVolume(Decibels db);
protected:
private:
};
/// A Windows Sound API implementation of the SoundSubsystem.
class WASAPISubsystem : public SoundSubsystem
{
public:
protected:
private:
};
}

View File

@@ -1,48 +0,0 @@
/// ReMixer
/// A Public Domain C++ Audio Playback Library
/// By william @ RedactedSoftware. Thanks to Dawsh & Maxine.
/// (c) 2024 Redacted Software
/// This work is explicitly dedicated to the public domain, for the hopeful betterment of the software industry.
/// @file StreamManager.h
/// @desc This class manages internal creation and storage of active Streams.
/// @edit 2024-08-06
#pragma once
#include <map>
#include "stream.h"
class TakenStreamIDException : public std::exception
{
};
//class StreamManager {
//public:
//static std::map<uint16_t, Stream *> streamList;
//StreamManager();
//StreamManager(const StreamManager&);
// Get stream using handle
//static Stream *GetStream(uint16_t handle)
//{
// return streamList.at(handle);
//}
// Return Stream handle
// TODO:
/*static Stream* CreateStream()
{
// Can we create the stream here and assign the handle on our side?
// or do you need to change it from outside
}
static void AddStream(Stream* stream)
{
streamList.emplace(stream->handle, stream);
}
// Iterator maybe?
// Fuck if I know what type is returned.
auto begin() { return streamList.begin(); };
auto end() { return streamList.end(); };
};*/

View File

@@ -1,8 +0,0 @@
//
// Created by josh on 7/16/25.
//
#ifndef WASAPIDEVICE_HPP
#define WASAPIDEVICE_HPP
#endif //WASAPIDEVICE_HPP

View File

@@ -14,9 +14,9 @@
#include <iostream>
#include <fstream>
#include <thread>
#include <ReMixer/stream.h>
#include <ReMixer/IStream.hpp>
#include <ReMixer/Sound.hpp>
#include <ReMixer/PulseDevice.h>
#include <include/Backend/Pulse/PulseDevice.h>
#include <ReMixer/ReMixer.h>
#include "ReMixer/Frequency.hpp"

View File

@@ -1,4 +1,4 @@
#include <ReMixer/PulseDevice.h>
#include <../../include/Backend/Pulse/PulseDevice.h>
void ReMixer::PulseAudioSubsystem::Play(ReMixer::PulseStream &stream, const ReMixer::Sound &sound) {

View File

@@ -1,4 +1,4 @@
#include <ReMixer/stream.h>
#include <ReMixer/IStream.hpp>
#include <ReMixer/Sound.hpp>
#include <uuid/uuid.h>
#include <iostream>

View File

@@ -1 +0,0 @@
#include <ReMixer/SoundSubsystem.h>

View File

@@ -1,3 +0,0 @@
//
// Created by Josh on 8/22/2024.
//