Some AI shite
Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -91,3 +91,5 @@ compile_commands.json
|
|||||||
# Conan build dir
|
# Conan build dir
|
||||||
build/
|
build/
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
|
venv
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ class daw_projectConan(ConanFile):
|
|||||||
def requirements(self):
|
def requirements(self):
|
||||||
self.requires("conan-test-lib/0.0.2")
|
self.requires("conan-test-lib/0.0.2")
|
||||||
self.requires("qt/6.10.1")
|
self.requires("qt/6.10.1")
|
||||||
|
self.requires("libsndfile/1.2.2")
|
||||||
|
|
||||||
def layout(self):
|
def layout(self):
|
||||||
self.folders.build = "build"
|
self.folders.build = "build"
|
||||||
self.folders.generators = "build/scripts"
|
self.folders.generators = "venv"
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
deps = PkgConfigDeps(self)
|
deps = PkgConfigDeps(self)
|
||||||
|
|||||||
12
meson.build
12
meson.build
@@ -1,13 +1,15 @@
|
|||||||
project('daw-exp ', 'cpp')
|
project('daw-exp ', 'cpp')
|
||||||
|
|
||||||
qt_dep = dependency('qt6', modules: ['Core', 'Widgets'])
|
qt_dep = dependency('qt6', modules: ['Core', 'Widgets'])
|
||||||
|
|
||||||
jack_dep = dependency('jack', required : true)
|
jack_dep = dependency('jack', required : true)
|
||||||
test_dep = dependency('conan-test-lib', required: true)
|
test_dep = dependency('conan-test-lib', required: true)
|
||||||
|
snd_dep = dependency('sndfile', required: true)
|
||||||
|
|
||||||
#executable('daw-project', 'src/engine/main.cpp',
|
appleframeworks_dep = dependency('appleframeworks',
|
||||||
# dependencies: [jack_dep, test_dep],
|
modules : ['AudioUnit', 'AudioToolbox', 'CoreAudio']
|
||||||
# install: true)
|
)
|
||||||
|
|
||||||
executable('daw-gui', 'src/gui/main.cpp',
|
executable('daw-gui', 'src/main.cpp',
|
||||||
dependencies: [qt_dep, test_dep],
|
dependencies: [qt_dep, test_dep, snd_dep, appleframeworks_dep],
|
||||||
install: true)
|
install: true)
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
// src/main.cpp
|
|
||||||
#include <jack/jack.h>
|
|
||||||
#include <cmath>
|
|
||||||
#include <iostream>
|
|
||||||
#include <atomic>
|
|
||||||
static std::atomic<jack_client_t*> g_client{nullptr};
|
|
||||||
static float g_phase = 0.0f;
|
|
||||||
static const float kFreq = 440.0f;
|
|
||||||
|
|
||||||
int process(jack_nframes_t nframes, void* arg) {
|
|
||||||
jack_port_t* port = static_cast<jack_port_t*>(arg);
|
|
||||||
float* out = (float*)jack_port_get_buffer(port, nframes);
|
|
||||||
jack_client_t* client = g_client.load();
|
|
||||||
if (!client) return 0;
|
|
||||||
|
|
||||||
jack_nframes_t sr = jack_get_sample_rate(client);
|
|
||||||
for (jack_nframes_t i = 0; i < nframes; ++i) {
|
|
||||||
out[i] = std::sinf(g_phase);
|
|
||||||
g_phase += 2.0f * static_cast<float>(M_PI) * kFreq / static_cast<float>(sr);
|
|
||||||
if (g_phase > 2.0f * static_cast<float>(M_PI)) g_phase -= 2.0f * static_cast<float>(M_PI);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
jack_status_t status;
|
|
||||||
jack_client_t* client = jack_client_open("cpp_jack_player", JackNullOption, &status);
|
|
||||||
if (!client) {
|
|
||||||
std::cerr << "Failed to open JACK client (status=" << status << ")\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
g_client.store(client);
|
|
||||||
|
|
||||||
jack_port_t* outport = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE,
|
|
||||||
JackPortIsOutput, 0);
|
|
||||||
if (!outport) {
|
|
||||||
std::cerr << "Failed to register output port\n";
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jack_set_process_callback(client, process, outport) != 0) {
|
|
||||||
std::cerr << "Failed to set process callback\n";
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jack_activate(client) != 0) {
|
|
||||||
std::cerr << "Failed to activate JACK client\n";
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Client active. Connect " << jack_get_client_name(client)
|
|
||||||
<< ":output to system:playback (e.g. with qjackctl). Press Enter to quit.\n";
|
|
||||||
std::cin.get();
|
|
||||||
|
|
||||||
jack_client_close(client);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
#include "qpushbutton.h"
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
void add_button()
|
|
||||||
{
|
|
||||||
QPushButton button ("Hello");
|
|
||||||
button.show();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#include <QApplication>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include "./control_panel.cpp"
|
|
||||||
#include <conan-test-lib.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
conan_test_lib();
|
|
||||||
QApplication app (argc, argv);
|
|
||||||
add_button();
|
|
||||||
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
||||||
110
src/main.cpp
Normal file
110
src/main.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include <AudioUnit/AudioUnit.h>
|
||||||
|
#include <AudioToolbox/AudioToolbox.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
constexpr double SAMPLE_RATE = 44100.0;
|
||||||
|
constexpr double FREQUENCY = 440.0; // A4
|
||||||
|
constexpr double AMPLITUDE = 0.25;
|
||||||
|
|
||||||
|
struct SineState {
|
||||||
|
double phase = 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
OSStatus renderCallback(
|
||||||
|
void* inRefCon,
|
||||||
|
AudioUnitRenderActionFlags* ioActionFlags,
|
||||||
|
const AudioTimeStamp* inTimeStamp,
|
||||||
|
UInt32 inBusNumber,
|
||||||
|
UInt32 inNumberFrames,
|
||||||
|
AudioBufferList* ioData)
|
||||||
|
{
|
||||||
|
auto* state = static_cast<SineState*>(inRefCon);
|
||||||
|
double phase = state->phase;
|
||||||
|
double phaseIncrement = 2.0 * M_PI * FREQUENCY / SAMPLE_RATE;
|
||||||
|
|
||||||
|
for (UInt32 frame = 0; frame < inNumberFrames; ++frame) {
|
||||||
|
float sample = static_cast<float>(std::sin(phase) * AMPLITUDE);
|
||||||
|
phase += phaseIncrement;
|
||||||
|
if (phase >= 2.0 * M_PI)
|
||||||
|
phase -= 2.0 * M_PI;
|
||||||
|
|
||||||
|
// Write same sample to all channels
|
||||||
|
for (UInt32 buffer = 0; buffer < ioData->mNumberBuffers; ++buffer) {
|
||||||
|
float* data = static_cast<float*>(ioData->mBuffers[buffer].mData);
|
||||||
|
data[frame] = sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->phase = phase;
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
AudioUnit audioUnit;
|
||||||
|
SineState state;
|
||||||
|
|
||||||
|
// Describe output unit
|
||||||
|
AudioComponentDescription desc{};
|
||||||
|
desc.componentType = kAudioUnitType_Output;
|
||||||
|
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||||
|
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||||
|
|
||||||
|
AudioComponent comp = AudioComponentFindNext(nullptr, &desc);
|
||||||
|
if (!comp) {
|
||||||
|
std::cerr << "Failed to find audio component\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioComponentInstanceNew(comp, &audioUnit);
|
||||||
|
|
||||||
|
// Set stream format
|
||||||
|
AudioStreamBasicDescription format{};
|
||||||
|
format.mSampleRate = SAMPLE_RATE;
|
||||||
|
format.mFormatID = kAudioFormatLinearPCM;
|
||||||
|
format.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
|
||||||
|
format.mBitsPerChannel = 32;
|
||||||
|
format.mChannelsPerFrame = 2;
|
||||||
|
format.mBytesPerFrame = sizeof(float) * format.mChannelsPerFrame;
|
||||||
|
format.mFramesPerPacket = 1;
|
||||||
|
format.mBytesPerPacket = format.mBytesPerFrame;
|
||||||
|
|
||||||
|
AudioUnitSetProperty(
|
||||||
|
audioUnit,
|
||||||
|
kAudioUnitProperty_StreamFormat,
|
||||||
|
kAudioUnitScope_Input,
|
||||||
|
0,
|
||||||
|
&format,
|
||||||
|
sizeof(format)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set render callback
|
||||||
|
AURenderCallbackStruct callback{};
|
||||||
|
callback.inputProc = renderCallback;
|
||||||
|
callback.inputProcRefCon = &state;
|
||||||
|
|
||||||
|
AudioUnitSetProperty(
|
||||||
|
audioUnit,
|
||||||
|
kAudioUnitProperty_SetRenderCallback,
|
||||||
|
kAudioUnitScope_Input,
|
||||||
|
0,
|
||||||
|
&callback,
|
||||||
|
sizeof(callback)
|
||||||
|
);
|
||||||
|
|
||||||
|
AudioUnitInitialize(audioUnit);
|
||||||
|
AudioOutputUnitStart(audioUnit);
|
||||||
|
|
||||||
|
std::cout << "Playing sine wave (Ctrl+C to quit)...\n";
|
||||||
|
while (true) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioOutputUnitStop(audioUnit);
|
||||||
|
AudioUnitUninitialize(audioUnit);
|
||||||
|
AudioComponentInstanceDispose(audioUnit);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user