JUCE: iOSでサンプリングレートとバッファサイズを変更する

##問題##
Projucerのテンプレートから作成したAudio Pluginは、Standalone版もビルドできてiOSでもそのまま動くが、Mac/WindowsにあるAudioの設定画面がデフォルトでは提供されない。iOSの場合必要ない機能が大半だが、サンプリングレートとバッファサイズは音質、レイテンシの面から調整したいところ。

##前提##
ProjucerでAudio Pluginを作成している。

##解決方法##
StandalonePluginHolderのインスタンスからAudioDeviceManagerを取得、そこからAudioIODeviceを取得して設定する。AudioIODeviceでは値の取得はできるが設定ができない。設定はAudioDeviceManagerを使って行う。

サンプルをgithubに置いておいた。
https://github.com/masanaohayashi/Ring2JUCETips/tree/main/IOSAudioDeviceTest1

以下、その抜粋。

```MainComponent.cpp
    juce::StandalonePluginHolder* holder = juce::StandalonePluginHolder::getInstance();
    if (holder != nullptr)
    {
        juce::AudioIODevice* device = holder->deviceManager.getCurrentAudioDevice();
        if (device != nullptr)
        {
            auto availableSampleRates = device->getAvailableSampleRates();
            auto currentSampleRate = device->getCurrentSampleRate();
            comboSampleRate->clear();
            for (int i = 0; i < availableSampleRates.size(); i++)
            {
                comboSampleRate->addItem(juce::String(availableSampleRates[i]), i + 1);
                if (availableSampleRates[i] == currentSampleRate)
                    comboSampleRate->setSelectedId(i + 1);
            }

            labelBitDepth->setText (juce::String(device->getCurrentBitDepth()), juce::dontSendNotification);

            auto availableBufferSizes = device->getAvailableBufferSizes();
            auto currentBufferSize = device->getCurrentBufferSizeSamples();
            comboBufferSize->clear();
            for (int i = 0; i < availableBufferSizes.size(); i++)
            {
                comboBufferSize->addItem(juce::String(availableBufferSizes[i]), i + 1);
                if (availableBufferSizes[i] == currentBufferSize)
                    comboBufferSize->setSelectedId(i + 1);
            }
        }
    }
```

```MainComponent.cpp
void MainComponent::comboBoxChanged (juce::ComboBox* comboBoxThatHasChanged)
{
    //[UsercomboBoxChanged_Pre]
    //[/UsercomboBoxChanged_Pre]

    if (comboBoxThatHasChanged == comboSampleRate.get())
    {
        //[UserComboBoxCode_comboSampleRate] -- add your combo box handling code here..
        juce::StandalonePluginHolder* holder = juce::StandalonePluginHolder::getInstance();
        if (holder != nullptr)
        {
            juce::AudioIODevice* device = holder->deviceManager.getCurrentAudioDevice();
            if (device != nullptr)
            {
                auto availableSampleRates = holder->deviceManager.getCurrentAudioDevice()->getAvailableSampleRates();
                auto value = comboBoxThatHasChanged->getSelectedId() - 1;
                if ((value >= 0) && (value < availableSampleRates.size()))
                {
                    juce::AudioDeviceManager::AudioDeviceSetup setup = holder->deviceManager.getAudioDeviceSetup();
                    setup.sampleRate = availableSampleRates[value];
                    auto error = holder->deviceManager.setAudioDeviceSetup(setup, true);
                    if (error.isNotEmpty())
                        labelError->setText (error, juce::dontSendNotification);
                }
            }
        }
        //[/UserComboBoxCode_comboSampleRate]
    }
    else if (comboBoxThatHasChanged == comboBufferSize.get())
    {
        //[UserComboBoxCode_comboBufferSize] -- add your combo box handling code here..
        juce::StandalonePluginHolder* holder = juce::StandalonePluginHolder::getInstance();
        if (holder != nullptr)
        {
            juce::AudioIODevice* device = holder->deviceManager.getCurrentAudioDevice();
            if (device != nullptr)
            {
                auto availableBufferSizes = holder->deviceManager.getCurrentAudioDevice()->getAvailableBufferSizes();
                auto value = comboBoxThatHasChanged->getSelectedId() - 1;
                if ((value >= 0) && (value < availableBufferSizes.size()))
                {
                    juce::AudioDeviceManager::AudioDeviceSetup setup = holder->deviceManager.getAudioDeviceSetup();
                    setup.bufferSize = availableBufferSizes[value];
                    auto error = holder->deviceManager.setAudioDeviceSetup(setup, true);
                    if (error.isNotEmpty())
                        labelError->setText (error, juce::dontSendNotification);
                }
            }
        }
        //[/UserComboBoxCode_comboBufferSize]
    }

    //[UsercomboBoxChanged_Post]
    //[/UsercomboBoxChanged_Post]
}
```