|
- /*!
- @file AudioUnitSDK/AUMIDIBase.cpp
- @copyright © 2000-2021 Apple Inc. All rights reserved.
- */
- #include <AudioUnitSDK/AUMIDIBase.h>
- #include <CoreMIDI/CoreMIDI.h>
-
- namespace ausdk {
-
- // MIDI CC data bytes
- constexpr uint8_t kMIDIController_AllSoundOff = 120u;
- constexpr uint8_t kMIDIController_ResetAllControllers = 121u;
- constexpr uint8_t kMIDIController_AllNotesOff = 123u;
-
- OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
- AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable)
- {
- (void)inScope;
- (void)inElement;
- (void)outDataSize;
- (void)outWritable;
-
- switch (inID) { // NOLINT if/else?!
- #if AUSDK_HAVE_XML_NAMES
- case kMusicDeviceProperty_MIDIXMLNames:
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- AUSDK_Require(GetXMLNames(nullptr) == noErr, kAudioUnitErr_InvalidProperty);
- outDataSize = sizeof(CFURLRef);
- outWritable = false;
- return noErr;
- #endif
-
- #if AUSDK_HAVE_MIDI_MAPPING
- case kAudioUnitProperty_AllParameterMIDIMappings:
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- outWritable = true;
- outDataSize = sizeof(AUParameterMIDIMapping) * mMIDIMapper->GetNumberMaps();
- return noErr;
-
- case kAudioUnitProperty_HotMapParameterMIDIMapping:
- case kAudioUnitProperty_AddParameterMIDIMapping:
- case kAudioUnitProperty_RemoveParameterMIDIMapping:
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- outWritable = true;
- outDataSize = sizeof(AUParameterMIDIMapping);
- return noErr;
- #endif
-
- default:
- return kAudioUnitErr_InvalidProperty;
- }
- }
-
- OSStatus AUMIDIBase::DelegateGetProperty(
- AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData)
- {
- (void)inScope;
- (void)inElement;
- (void)outData;
-
- switch (inID) { // NOLINT if/else?!
- #if AUSDK_HAVE_XML_NAMES
- case kMusicDeviceProperty_MIDIXMLNames:
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- return GetXMLNames(static_cast<CFURLRef*>(outData));
- #endif
-
- #if AUSDK_HAVE_MIDI_MAPPING
- case kAudioUnitProperty_AllParameterMIDIMappings: {
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- AUParameterMIDIMapping* const maps = (static_cast<AUParameterMIDIMapping*>(outData));
- mMIDIMapper->GetMaps(maps);
- return noErr;
- }
-
- case kAudioUnitProperty_HotMapParameterMIDIMapping: {
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- AUParameterMIDIMapping* const map = (static_cast<AUParameterMIDIMapping*>(outData));
- mMIDIMapper->GetHotParameterMap(*map);
- return noErr;
- }
- #endif
-
- default:
- return kAudioUnitErr_InvalidProperty;
- }
- }
-
- OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
- AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
- {
- (void)inScope;
- (void)inElement;
- (void)inData;
- (void)inDataSize;
-
- switch (inID) {
-
- #if AUSDK_HAVE_MIDI_MAPPING
- case kAudioUnitProperty_AddParameterMIDIMapping: {
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- const auto* const maps = static_cast<const AUParameterMIDIMapping*>(inData);
- mMIDIMapper->AddParameterMapping(
- maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
- mAUBaseInstance.PropertyChanged(
- kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
- return noErr;
- }
-
- case kAudioUnitProperty_RemoveParameterMIDIMapping: {
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- const auto* const maps = static_cast<const AUParameterMIDIMapping*>(inData);
- bool didChange = false;
- mMIDIMapper->RemoveParameterMapping(
- maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
- if (didChange) {
- mAUBaseInstance.PropertyChanged(
- kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
- }
- return noErr;
- }
-
- case kAudioUnitProperty_HotMapParameterMIDIMapping: {
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- const auto& map = *static_cast<const AUParameterMIDIMapping*>(inData);
- mMIDIMapper->SetHotMapping(map);
- return noErr;
- }
-
- case kAudioUnitProperty_AllParameterMIDIMappings: {
- AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
- AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
- AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
- const auto* const mappings = static_cast<const AUParameterMIDIMapping*>(inData);
- mMIDIMapper->ReplaceAllMaps(
- mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
- return noErr;
- }
- #endif
-
- default:
- return kAudioUnitErr_InvalidProperty;
- }
- }
-
- constexpr uint8_t MIDIStatusNibbleValue(uint8_t status) noexcept { return (status & 0xF0U) >> 4u; }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // AUMIDIBase::HandleMIDIEvent
- //
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- OSStatus AUMIDIBase::HandleMIDIEvent(
- UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
- {
- if (!mAUBaseInstance.IsInitialized()) {
- return kAudioUnitErr_Uninitialized;
- }
-
- #if AUSDK_HAVE_MIDI_MAPPING
- // you potentially have a choice to make here - if a param mapping matches, do you still want to
- // process the MIDI event or not. The default behaviour is to continue on with the MIDI event.
- if (mMIDIMapper) {
- if (mMIDIMapper->HandleHotMapping(status, channel, data1, mAUBaseInstance)) {
- mAUBaseInstance.PropertyChanged(
- kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
- } else {
- mMIDIMapper->FindParameterMapEventMatch(
- status, channel, data1, data2, inStartFrame, mAUBaseInstance);
- }
- }
- #endif
- switch (MIDIStatusNibbleValue(status)) {
- case kMIDICVStatusNoteOn:
- if (data2 != 0u) {
- return HandleNoteOn(channel, data1, data2, inStartFrame);
- } else {
- // zero velocity translates to note off
- return HandleNoteOff(channel, data1, data2, inStartFrame);
- }
-
- case kMIDICVStatusNoteOff:
- return HandleNoteOff(channel, data1, data2, inStartFrame);
-
- default:
- return HandleNonNoteEvent(status, channel, data1, data2, inStartFrame);
- }
- }
-
- OSStatus AUMIDIBase::HandleNonNoteEvent(
- UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
- {
- switch (MIDIStatusNibbleValue(status)) {
- case kMIDICVStatusPitchBend:
- return HandlePitchWheel(channel, data1, data2, inStartFrame);
-
- case kMIDICVStatusProgramChange:
- return HandleProgramChange(channel, data1);
-
- case kMIDICVStatusChannelPressure:
- return HandleChannelPressure(channel, data1, inStartFrame);
-
- case kMIDICVStatusControlChange: {
- switch (data1) {
- case kMIDIController_AllNotesOff:
- return HandleAllNotesOff(channel);
-
- case kMIDIController_ResetAllControllers:
- return HandleResetAllControllers(channel);
-
- case kMIDIController_AllSoundOff:
- return HandleAllSoundOff(channel);
-
- default:
- return HandleControlChange(channel, data1, data2, inStartFrame);
- }
- }
-
- case kMIDICVStatusPolyPressure:
- return HandlePolyPressure(channel, data1, data2, inStartFrame);
-
- default:
- return noErr;
- }
- }
-
- OSStatus AUMIDIBase::SysEx(const UInt8* inData, UInt32 inLength)
- {
- if (!mAUBaseInstance.IsInitialized()) {
- return kAudioUnitErr_Uninitialized;
- }
-
- return HandleSysEx(inData, inLength);
- }
-
- } // namespace ausdk
|