Nothing has happend
Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
This commit is contained in:
@@ -20,6 +20,7 @@ class daw_projectConan(ConanFile):
|
|||||||
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")
|
self.requires("libsndfile/1.2.2")
|
||||||
|
self.requires("gtest/1.17.0")
|
||||||
|
|
||||||
def layout(self):
|
def layout(self):
|
||||||
self.folders.build = "build"
|
self.folders.build = "build"
|
||||||
|
|||||||
113
coreaudio.cpp
Normal file
113
coreaudio.cpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
7
src/gui/editor.cpp
Normal file
7
src/gui/editor.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
QPushButton renderButton()
|
||||||
|
{
|
||||||
|
QPushButton button ("Hello world !");
|
||||||
|
return button;
|
||||||
|
}
|
||||||
118
src/main.cpp
118
src/main.cpp
@@ -1,110 +1,20 @@
|
|||||||
#include <AudioUnit/AudioUnit.h>
|
#include <QApplication>
|
||||||
#include <AudioToolbox/AudioToolbox.h>
|
#include <QPushButton>
|
||||||
#include <cmath>
|
#include <QWidget>
|
||||||
#include <iostream>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
constexpr double SAMPLE_RATE = 44100.0;
|
void renderButton(QWidget *parent) {
|
||||||
constexpr double FREQUENCY = 440.0; // A4
|
QPushButton *button = new QPushButton("Hello world!", parent);
|
||||||
constexpr double AMPLITUDE = 0.25;
|
button->show();
|
||||||
|
|
||||||
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() {
|
int main(int argc, char **argv) {
|
||||||
AudioUnit audioUnit;
|
QApplication app (argc, argv);
|
||||||
SineState state;
|
|
||||||
|
QWidget window;
|
||||||
|
window.resize(300, 200);
|
||||||
|
window.show();
|
||||||
|
|
||||||
// Describe output unit
|
renderButton(&window);
|
||||||
AudioComponentDescription desc{};
|
return app.exec();
|
||||||
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