Initial Commit

This commit is contained in:
2024-08-06 22:36:34 -04:00
commit 57937e322b
11 changed files with 360 additions and 0 deletions

50
CMakeLists.txt Normal file
View File

@@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.18)
project(ReMixer
VERSION 1.0
LANGUAGES CXX
)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(cmake/CPM.cmake)
CPMAddPackage(
NAME uuid
URL https://git.redacted.cc/Redacted/uuid/archive/Release-1.zip
)
if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "In-Source builds are not allowed")
endif()
file(GLOB_RECURSE HEADERS "include/ReMixer/*.h")
if(UNIX AND NOT APPLE)
file(GLOB_RECURSE SOURCES "src/shared/*.cpp" "src/linux/*.cpp")
endif()
if(WIN32)
file(GLOB_RECURSE HEADERS "include/ReMixer/*.h")
file(GLOB_RECURSE SOURCES "src/shared/*.cpp" "src/windows/*.cpp")
endif()
include_directories("include" ${uuid_SOURCE_DIR}/include)
add_library(ReMixer ${SOURCES})
add_executable(ReMixer-Test main.cpp)
set_target_properties(ReMixer PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(ReMixer-Test PROPERTIES LINKER_LANGUAGE CXX)
if(UNIX AND NOT APPLE)
target_link_libraries(ReMixer PUBLIC vorbisfile vorbis pulse-simple pulse uuid)
endif()
if(WIN32)
#target_link_libraries(Remixer PUBLIC)
endif()
target_link_libraries(ReMixer-Test PUBLIC ReMixer)

24
cmake/CPM.cmake Normal file
View File

@@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT
#
# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
set(CPM_DOWNLOAD_VERSION 0.38.7)
set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5")
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()
# Expand relative path. This is important if the provided path contains a tilde (~)
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
file(DOWNLOAD
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
)
include(${CPM_DOWNLOAD_LOCATION})

10
include/ReMixer/ReMixer.h Normal file
View File

@@ -0,0 +1,10 @@
#pragma once
#include <ReMixer/stream.h>
#include <ReMixer/sound.h>
namespace ReMixer {
uint16_t createStream(const std::string& application_name, const std::string& stream_name, SampleRate sample_rate, StreamMode mode);
}
// this dick

View File

@@ -0,0 +1,48 @@
/// 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(); };
};

43
include/ReMixer/sound.h Normal file
View File

@@ -0,0 +1,43 @@
#pragma once
#include <vector>
#include <pulse/pulseaudio.h>
#include <pulse/simple.h>
#include <filesystem>
class PlaybackDevice {};
class InputDevice {};
class Sound {
private:
std::vector<uint8_t> audio_data;
public:
std::vector<uint8_t> getAudioData();
void setAudioData(const std::vector<uint8_t>& audioData);
uint8_t* ptr() { return audio_data.data();}
[[nodiscard]] const uint8_t* ptr() const { return audio_data.data();}
Sound() = default;
explicit Sound(const std::vector<uint8_t>& audioData);
};
/// Short (sub-10-second) audio clips via OGG vorbis format.
class SFX : public Sound {
public:
SFX() = default;
SFX(const std::filesystem::path& sfx_file_path)
{
}
};
/// Longer (>10 second) audio via WAV format.
class Song : public Sound {
public:
Song() = default;
Song(const std::filesystem::path& song_file_path)
{
}
};

50
include/ReMixer/stream.h Normal file
View File

@@ -0,0 +1,50 @@
/// 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 stream.h
/// @desc An audio stream class that interfaces with pulseaudio, etc, to play back sounds.
/// @edit 2024-08-06
#pragma once
#include <string>
#include <vector>
#include <pulse/simple.h>
enum class StreamMode : bool {
MONO = false,
STEREO = true
};
enum class SampleRate : unsigned int {
STANDARD = 44100,
HIGH = 48000
};
class Stream {
private:
std::string application_name;
std::string stream_name;
StreamMode mode;
SampleRate sample_rate;
size_t bufferSize;
std::vector<char> buffer;
#ifdef __linux__
pa_simple* stream = nullptr;
#endif
#ifdef _WIN32
#endif
public:
uint16_t handle;
Stream(const std::string& application_name, const std::string& stream_name, SampleRate sample_rate, StreamMode mode);
unsigned int numChannels();
void erase();
};
inline std::vector<Stream*> streamList;

81
main.cpp Normal file
View File

@@ -0,0 +1,81 @@
/// 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
#include <iostream>
#include <ReMixer/stream.h>
#include <ReMixer/sound.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include <iostream>
#include <fstream>
void decodeVorbis(const char* inputFile, const char* outputFile)
{
OggVorbis_File vf;
FILE* inFile = fopen(inputFile, "rb");
if (!inFile) {
std::cerr << "Error opening input file." << std::endl; return;
}
if (ov_open(inFile, &vf, NULL, 0) < 0) {
std::cerr << "Error opening Ogg Vorbis file." << std::endl;
fclose(inFile);
return;
}
vorbis_info* vi = ov_info(&vf, -1);
std::ofstream outFile(outputFile, std::ios::binary);
if (!outFile.is_open()) {
std::cerr << "Error opening output file." << std::endl;
ov_clear(&vf);
fclose(inFile);
return;
}
char pcmout[4096];
int current_section;
long bytes;
while ((bytes = ov_read(&vf, pcmout, sizeof(pcmout), 0, 2, 1, &current_section)) > 0) {
outFile.write(pcmout, bytes);
}
outFile.close();
ov_clear(&vf);
fclose(inFile);
}
[[noreturn]] int main() {
const char* inputFile = "input.ogg";
const char* outputFile = "output.raw";
decodeVorbis(inputFile, outputFile);
std::cout << "Decoding complete. Raw audio data saved to " << outputFile << std::endl;
Stream stream("ReMixer-Test", "Main", SampleRate::STANDARD, StreamMode::STEREO);
bool keep_runnin = true;
while (keep_runnin) {
}
return 0;
}
//Windows :(
#ifdef _WIN32
extern "C" {
int wmain(int argc, wchar_t* argv[]) {
return main();
}
}
#endif

7
src/linux/ReMixer.cpp Normal file
View File

@@ -0,0 +1,7 @@
#include <ReMixer/ReMixer.h>
uint16_t ReMixer::createStream(const std::string& application_name, const std::string& stream_name, SampleRate sample_rate, StreamMode mode) {
auto s = Stream(application_name, stream_name, sample_rate, mode);
return s.handle;
}

View File

@@ -0,0 +1 @@
#include "ReMixer/StreamManager.h"

12
src/linux/sound.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include <ReMixer/sound.h>
std::vector<uint8_t> Sound::getAudioData() {
return audio_data;
}
void Sound::setAudioData(const std::vector<uint8_t>& audioData) {
audio_data = audioData;
}
Sound::Sound(const std::vector<uint8_t>& audioData) {
setAudioData(audioData);
}

34
src/linux/stream.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include <ReMixer/stream.h>
#include <ReMixer/sound.h>
#include <uuid/uuid.h>
Stream::Stream(const std::string& name, const std::string& stream_name, SampleRate sample_rate, StreamMode mode) {
this->application_name = name;
this->stream_name = stream_name;
this->sample_rate = sample_rate;
this->mode = mode;
handle = UUID::dice(0, 65535);
//50ms.
bufferSize = (unsigned int) sample_rate * numChannels() * 2 / 20;
pa_sample_spec sample_spec = {.format = PA_SAMPLE_S16LE, .rate = (uint32_t) sample_rate, .channels = (uint8_t) numChannels()};
pa_buffer_attr buffer_attr = {buffer_attr.maxlength = (uint32_t) -1, buffer_attr.tlength = bufferSize, buffer_attr.prebuf = (uint32_t) -1,
buffer_attr.minreq = (uint32_t) -1, buffer_attr.fragsize = (uint32_t) -1};
stream = pa_simple_new(nullptr, name.c_str(), PA_STREAM_PLAYBACK, nullptr, name.c_str(), &sample_spec, nullptr, &buffer_attr, nullptr);
streamList.push_back(new Stream(*this));
}
unsigned int Stream::numChannels() {
return (unsigned int) mode + 1;
}
void Stream::erase() {
pa_simple_free(stream);
for (int i = 0; i < streamList.size(); i++)
if (this == streamList[i])
streamList.erase(streamList.begin() + i);
}