Skip to content

Instantly share code, notes, and snippets.

@COx2
Last active April 20, 2020 05:04
Show Gist options
  • Save COx2/e51455828f580711779e0b7900b5476a to your computer and use it in GitHub Desktop.
Save COx2/e51455828f580711779e0b7900b5476a to your computer and use it in GitHub Desktop.
JUCEのAudioDeviceManagerに独自のAudioDeviceを追加する
/*
==============================================================================
This file was auto-generated!
==============================================================================
*/
#include "MainComponent.h"
#include "MyAudioDevice.h"
//==============================================================================
MainComponent::MainComponent()
{
deviceManager.addAudioDeviceType(new SineWaveAudioIODeviceType());
setSize(800, 600);
}
/*
==============================================================================
MyAudioDevice.cpp
Created: 11 Jul 2019 3:50:56pm
Author: COx2
==============================================================================
*/
#include "MyAudioDevice.h"
//==============================================================================
SineWaveAudioIODevice::SineWaveAudioIODevice(const String & deviceName, const String & typeName, const String & outputDeviceID, const String & inputDeviceID)
: AudioIODevice(deviceName, typeName)
{
}
SineWaveAudioIODevice::~SineWaveAudioIODevice()
{
}
Array<double> SineWaveAudioIODevice::getAvailableSampleRates()
{
Array<double> ret;
ret.add(44100);
ret.add(48000);
ret.add(88200);
ret.add(96000);
return ret;
}
Array<int> SineWaveAudioIODevice::getAvailableBufferSizes()
{
Array<int> ret;
ret.add(256);
ret.add(512);
ret.add(1024);
return ret;
}
int SineWaveAudioIODevice::getDefaultBufferSize()
{
return bufferSize;
}
String SineWaveAudioIODevice::open(const BigInteger & inputChannels, const BigInteger & outputChannels, double sampleRate_, int bufferSizeSamples)
{
ScopedLock lock(audioDeviceLock);
sampleRate = sampleRate_;
channelsIn = inputChannels;
channelsOut = outputChannels;
bufferSize = bufferSizeSamples;
numChannelsIn = channelsIn.countNumberOfSetBits();
numChannelsOut = channelsOut.countNumberOfSetBits();
closed = false;
return String();
}
void SineWaveAudioIODevice::close()
{
stop();
closed = true;
}
bool SineWaveAudioIODevice::isOpen()
{
return ! closed;
}
void SineWaveAudioIODevice::start(AudioIODeviceCallback * callback)
{
deviceManagerCallbackHandler = callback;
deviceManagerCallbackHandler->audioDeviceAboutToStart(this);
startTimerHz(30);
}
void SineWaveAudioIODevice::stop()
{
if (deviceManagerCallbackHandler != nullptr)
{
ScopedLock lock(audioDeviceLock);
stopTimer();
deviceManagerCallbackHandler->audioDeviceStopped();
deviceManagerCallbackHandler = nullptr;
}
}
bool SineWaveAudioIODevice::isPlaying()
{
return deviceManagerCallbackHandler != nullptr;
}
String SineWaveAudioIODevice::getLastError()
{
return String();
}
void SineWaveAudioIODevice::timerCallback()
{
AudioBuffer<float> inputBuffer(numChannelsIn, bufferSize);
AudioBuffer<float> outputBuffer(numChannelsOut, bufferSize);
for (int ch_index = 0; ch_index < inputBuffer.getNumChannels(); ++ch_index)
{
auto ch_data = inputBuffer.getWritePointer(ch_index);
for (int sample = 0; sample < inputBuffer.getNumSamples(); ++sample)
{
ch_data[sample] = sinf(juce::MathConstants<float>::twoPi * sample / inputBuffer.getNumSamples()) * 0.5f;
}
}
deviceManagerCallbackHandler->audioDeviceIOCallback(
inputBuffer.getArrayOfReadPointers(), inputBuffer.getNumChannels(),
outputBuffer.getArrayOfWritePointers(), outputBuffer.getNumChannels(),
bufferSize
);
}
//==============================================================================
StringArray SineWaveAudioIODeviceType::getDeviceNames(bool wantInputNames) const
{
if(wantInputNames)
return inputDeviceNames;
else
return outputDeviceNames;
}
int SineWaveAudioIODeviceType::getDefaultDeviceIndex(bool forInput) const
{
return 0;
}
int SineWaveAudioIODeviceType::getIndexOfDevice(AudioIODevice * device, bool asInput) const
{
if (asInput)
switch (device->getActiveInputChannels().getHighestBit())
{
case 0:
case 1:
return 0;
break;
case 2:
case 3:
return 1;
break;
default:
return -1;
break;
}
else
switch (device->getActiveOutputChannels().getHighestBit())
{
case 0:
case 1:
return 0;
break;
case 2:
case 3:
return 1;
break;
default:
return -1;
break;
}
}
AudioIODevice * SineWaveAudioIODeviceType::createDevice(const String & outputDeviceName, const String & inputDeviceName)
{
DBG("SineWaveAudioIODeviceType::createDevice");
std::unique_ptr<SineWaveAudioIODevice> device;
device.reset(new SineWaveAudioIODevice(outputDeviceName, getTypeName(), outputDeviceName, inputDeviceName));
return device.release();
}
/*
==============================================================================
MyAudioDevice.h
Created: 11 Jul 2019 3:50:56pm
Author: COx2
==============================================================================
*/
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
class SineWaveAudioIODevice : public AudioIODevice, private Timer
{
public:
SineWaveAudioIODevice(const String& deviceName, const String& typeName, const String& outputDeviceID, const String& inputDeviceID);
~SineWaveAudioIODevice() override;
virtual StringArray getOutputChannelNames() override { return { "Out1", "Out2", "Out3", "Out4" }; };
virtual StringArray getInputChannelNames() override { return{ "In1", "In2", "In3", "In4" }; };
virtual Array<double> getAvailableSampleRates() override;
virtual Array<int> getAvailableBufferSizes() override;
virtual int getDefaultBufferSize() override;
virtual String open(const BigInteger& inputChannels, const BigInteger& outputChannels, double sampleRate, int bufferSizeSamples) override;
virtual void close() override;
virtual bool isOpen() override;
virtual void start(AudioIODeviceCallback* callback) override;
virtual void stop() override;
virtual bool isPlaying() override;
virtual String getLastError() override;
//==============================================================================
virtual int getCurrentBufferSizeSamples() override { return bufferSize; };
virtual double getCurrentSampleRate() override { return sampleRate; };
virtual int getCurrentBitDepth() override { return bitDepth; };
virtual BigInteger getActiveOutputChannels() const override { return channelsOut; };
virtual BigInteger getActiveInputChannels() const override { return channelsIn; };
virtual int getOutputLatencyInSamples() override { return 0; };
virtual int getInputLatencyInSamples() override { return 0; };
private:
virtual void timerCallback() override;
int bufferSize{ 512 };
double sampleRate{ 44100 };
int bitDepth{ 32 };
BigInteger channelsIn, channelsOut;
int numChannelsIn, numChannelsOut;
CriticalSection audioDeviceLock;
bool closed{ false };
// AudioDeviceMangerで保持しているコールバック先のオブジェクト
AudioIODeviceCallback* deviceManagerCallbackHandler{ nullptr };
};
class SineWaveAudioIODeviceType : public AudioIODeviceType
{
public:
SineWaveAudioIODeviceType()
: AudioIODeviceType("SineWave Audio Device")
{};
~SineWaveAudioIODeviceType() override
{};
virtual void scanForDevices() override {}
virtual StringArray getDeviceNames(bool wantInputNames = false) const override;
virtual int getDefaultDeviceIndex(bool forInput) const override;
virtual int getIndexOfDevice(AudioIODevice* device, bool asInput) const override;
virtual bool hasSeparateInputsAndOutputs() const override { return true; };
virtual AudioIODevice* createDevice(const String& outputDeviceName, const String& inputDeviceName) override;
private:
StringArray inputDeviceNames { "SineWave Input1", "SineWave Input2" };
StringArray outputDeviceNames{ "SineWave Output1", "SineWave Output2" };
};
@COx2
Copy link
Author

COx2 commented Jul 11, 2019

AudioIODeviceとAudioIODeviceTypeをそれぞれ継承して、AudioDeviceManagerに追加すれば、JUCEのデザインパターンに組み込まれるような仕組みになっている。
AudioIODevice...NativeなオーディオAPIの実装を書く
AudioIODeviceType...AudioIODeviceの”型情報”みたいなもの。インスタンス生成・メタ情報を司る

@meteorsnows
Copy link

meteorsnows commented Apr 20, 2020

I am beginner to CPP. How to solve this:

Severity Code Description Project File Line Suppression State
Error C2664 'void juce::AudioDeviceManager::addAudioDeviceType(std::unique_ptr<juce::AudioIODeviceType,std::default_delete<_Ty>>)': cannot convert argument 1 from 'SineWaveAudioIODeviceType *' to 'std::unique_ptr<juce::AudioIODeviceType,std::default_delete<_Ty>>' AudioPluginHost_App c:\juce\extras\audiopluginhost\source\ui\mainhostwindow.cpp 555

@COx2
Copy link
Author

COx2 commented Apr 20, 2020

@meteorsnows
I think you use an upper version of JUCE library than my gist used.

I think If you rewrite your code like below, it will be good.

https://gist.github.com/COx2/e51455828f580711779e0b7900b5476a#file-maincomponent-cpp-L16

deviceManager.addAudioDeviceType(std::make_unique<SineWaveAudioIODeviceType>());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment