A minimal, working template for creating iPad AUv3 MIDI effect plugins using JUCE
This template provides everything you need to get started with iPad AUv3 plugin development. It includes a complete, tested foundation that builds and runs on iPad hardware, with comprehensive documentation for customization and deployment.
- macOS with Xcode 14.0+
- JUCE 8.0+ framework
- Apple Developer Account (paid, $99/year)
- iPad running iOS 15.0+ for testing
# Download or clone this template
git clone https://github.com/yourname/iPad-AUv3-MIDI-Template.git
cd iPad-AUv3-MIDI-Template# Open the JUCE project
open iPad-AUv3-MIDI-Template.jucer-
Project Settings:
- Change project name from "iPad AUv3 MIDI Template"
- Update company name, website, email
- Set unique bundle identifier:
com.yourcompany.yourplugin
-
Plugin Information:
- Plugin name: "Your Plugin Name"
- Plugin description: Update to describe your plugin
- Plugin manufacturer code: Change from "YrCo"
- Plugin code: Change from "YrPl"
-
AUv3 Configuration:
- Keep AUv3 bundle ID as:
com.yourcompany.yourplugin.AUv3 - Keep iOS deployment target at 15.0+
- Keep architecture as arm64
- Keep AUv3 bundle ID as:
- Click "Save Project and Open in IDE" in Projucer
- Select your development team in Xcode signing settings
- Build and run on your iPad
iPad-AUv3-MIDI-Template/
├── iPad-AUv3-MIDI-Template.jucer # JUCE project file
├── Source/ # C++ source code
│ ├── PluginProcessor.h # Audio processor header
│ ├── PluginProcessor.cpp # Audio processor implementation
│ ├── PluginEditor.h # UI editor header
│ └── PluginEditor.cpp # UI editor implementation
├── README.md # This file
├── DEPLOYMENT_GUIDE.md # Detailed deployment instructions
└── LICENSE # CC0 Public Domain license
- ✅ iPad-optimized project settings (iOS 15.0+, arm64)
- ✅ Proper bundle identifier hierarchy (prevents installation issues)
- ✅ AUv3-only build (no unnecessary standalone app)
- ✅ Touch-friendly UI sizing (44pt minimum touch targets)
- ✅ Responsive layout (portrait/landscape support)
- ✅ Thread-safe MIDI processing using
MidiMessageCollector - ✅ Real-time audio thread safety (no blocking operations)
- ✅ MIDI input/output routing properly configured
- ✅ Example MIDI note generation (customizable)
- ✅ Zero compilation warnings (Xcode 16.4+ tested)
- ✅ Modern C++ practices (JUCE 8.0+ compatibility)
- ✅ Comprehensive documentation (every function documented)
- ✅ Memory leak detection (JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR)
- ✅ iPad-specific optimizations (memory, touch, performance)
- ✅ Tested on hardware (physical iPad validation)
- ✅ Host app compatibility (AUM, Logic Pro for iPad)
- ✅ Proper plugin registration (appears correctly in hosts)
- ✅ State save/restore (parameter persistence)
- ✅ Professional visual design (modern, clean interface)
The template uses generic names that you should customize:
In PluginProcessor.h and PluginProcessor.cpp:
- Rename
TemplateAudioProcessor→YourPluginAudioProcessor
In PluginEditor.h and PluginEditor.cpp:
- Rename
TemplateAudioProcessorEditor→YourPluginAudioProcessorEditor
The template includes a simple "Send MIDI Note" example. Replace this with your plugin's logic:
// In PluginProcessor.cpp - processBlock() method
void YourPluginAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer,
juce::MidiBuffer& midiMessages)
{
buffer.clear(); // MIDI effect doesn't process audio
// Add your MIDI processing logic here:
// - Analyze incoming MIDI messages
// - Generate new MIDI data
// - Transform/filter existing MIDI
// - Apply your algorithm/effects
// Get any MIDI generated by UI thread
juce::MidiBuffer collectedMidi;
midiCollector.removeNextBlockOfMessages (collectedMidi, buffer.getNumSamples());
midiMessages.addEvents (collectedMidi, 0, buffer.getNumSamples(), 0);
}The template provides a foundation with iPad-optimized controls:
// In PluginEditor.cpp - customize the resized() method for your layout
void YourPluginAudioProcessorEditor::resized()
{
auto bounds = getLocalBounds();
bounds.reduce(20, 20); // Touch-friendly padding
// Add your custom UI layout here
// Remember: minimum 44pt touch targets for iPad
// Example: Custom control layout
mySlider.setBounds(bounds.removeFromTop(60));
myButton.setBounds(bounds.removeFromTop(44).withSizeKeepingCentre(200, 44));
myLabel.setBounds(bounds.removeFromTop(30));
}Add any parameters your plugin needs:
// In PluginProcessor.h - add parameter declarations
private:
juce::AudioParameterFloat* gainParameter;
juce::AudioParameterChoice* modeParameter;
// In PluginProcessor.cpp constructor - add parameters
TemplateAudioProcessor::TemplateAudioProcessor()
{
addParameter(gainParameter = new juce::AudioParameterFloat(
juce::ParameterID("gain", 1), "Gain", 0.0f, 1.0f, 0.5f));
addParameter(modeParameter = new juce::AudioParameterChoice(
juce::ParameterID("mode", 1), "Mode",
juce::StringArray{"Mode A", "Mode B", "Mode C"}, 0));
}- Configuration: Use "Release" for final testing
- Destination: Select your physical iPad (not simulator)
- Signing: Ensure development team is selected
- Build → Xcode will install to your iPad automatically
- Trust Profile → Settings → General → VPN & Device Management
- Test in Host → Open AUM, Logic Pro, or other AUv3 host
- Verify Function → Load plugin and test MIDI functionality
See DEPLOYMENT_GUIDE.md for detailed troubleshooting steps covering:
- Bundle identifier issues
- Code signing problems
- Plugin not appearing in hosts
- Development profile setup
- Common build failures
Before releasing your plugin, verify:
- Builds without warnings in Xcode Release configuration
- Installs on iPad without "Untrusted Developer" issues
- Appears in host apps (AUM, Logic Pro for iPad, etc.)
- UI displays correctly in portrait and landscape orientations
- Touch targets are at least 44pt for iPad usability
- MIDI input/output functions as expected
- Parameters save/restore correctly when host saves project
- No crashes during normal operation and edge cases
- Memory usage is reasonable (check in Xcode Instruments)
- Plugin survives host app backgrounding/foregrounding
// Example: MIDI message analysis and transformation
for (const auto metadata : midiMessages)
{
auto message = metadata.getMessage();
if (message.isNoteOn())
{
// Transform note-on messages
auto newNote = transformNote(message.getNoteNumber());
auto newVelocity = transformVelocity(message.getVelocity());
midiMessages.addEvent(juce::MidiMessage::noteOn(
message.getChannel(), newNote, newVelocity),
metadata.samplePosition);
}
}// In PluginEditor.cpp - paint() method for custom drawing
void YourPluginAudioProcessorEditor::paint (juce::Graphics& g)
{
// Custom background
g.fillAll(juce::Colours::black);
// Custom graphics for your plugin's visual feedback
// Use iPad-appropriate sizes and colors
g.setColour(juce::Colours::white);
g.drawText("Your Plugin", getLocalBounds(),
juce::Justification::centred, true);
}// Use Timer for smooth UI updates
class YourPluginAudioProcessorEditor : public juce::AudioProcessorEditor,
private juce::Timer
{
private:
void timerCallback() override
{
// Update UI based on processor state
// Repaint only what's necessary for performance
repaint();
}
};- JUCE Forum: https://forum.juce.com/ - Active community support
- Apple Developer Forums: iOS-specific AUv3 questions
- Stack Overflow: Tag questions with
juce,auv3,ios-audio
This template is in the public domain (CC0 license). Feel free to:
- Submit improvements via pull requests
- Create variations for specific use cases
- Share your plugins built with this template
- Help other developers in the community
When you've built something with this template:
- Submit to App Store for wide distribution
- Share on forums (JUCE, iOS audio communities)
- Create tutorials to help other developers
- Open source your plugin to contribute back
This template is released under CC0 1.0 Universal (Public Domain).
You can use this template for any purpose, including commercial projects, without attribution. However, attribution is appreciated if you'd like to help others discover this resource.
Built with:
- JUCE Framework - Cross-platform audio framework
- Apple iOS SDK - AUv3 and Core Audio frameworks
- Community Feedback - From iOS audio developer community
Special thanks to the JUCE team and iOS audio development community for their support and knowledge sharing.
Ready to build your iPad AUv3 MIDI plugin? 🎵
Start with this template and focus on your unique audio processing algorithms rather than setup complexities. The foundation is solid - now make it your own!