Skip to content

Commit

Permalink
Merge pull request #37 from kNoAPP/velocity
Browse files Browse the repository at this point in the history
Adds support for Velocity parameter
  • Loading branch information
rodydavis authored Aug 6, 2023
2 parents b37e9e2 + b46db8e commit d4a3977
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 30 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Play and Stop the Midi Notes

```dart
FlutterMidi.playMidiNote(midi: 60);
FlutterMidi.playMidiNote(midi: 60, velocity: 120);
FlutterMidi.stopMidiNote(midi: 60);
FlutterMidi.stopMidiNote(midi: 60, velocity: 120);
```
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,20 @@ public void onMethodCall(MethodCall call, Result result) {
}
} else if (call.method.equals("play_midi_note")) {
int _note = call.argument("note");
int _velocity = call.argument("velocity");
try {
ShortMessage msg = new ShortMessage();
msg.setMessage(ShortMessage.NOTE_ON, 0, _note, 127);
msg.setMessage(ShortMessage.NOTE_ON, 0, _note, _velocity);
recv.send(msg, -1);
} catch (InvalidMidiDataException e) {
e.printStackTrace();
}
} else if (call.method.equals("stop_midi_note")) {
int _note = call.argument("note");
int _velocity = call.argument("velocity");
try {
ShortMessage msg = new ShortMessage();
msg.setMessage(ShortMessage.NOTE_OFF, 0, _note, 127);
msg.setMessage(ShortMessage.NOTE_OFF, 0, _note, _velocity);
recv.send(msg, -1);
} catch (InvalidMidiDataException e) {
e.printStackTrace();
Expand Down
8 changes: 4 additions & 4 deletions ios/Classes/AudioUnitMIDISynth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ class AudioUnitMIDISynth: NSObject {
//

/// Send a note on message using patch2 on channel 0
func playPitch(midi: Int) {
func playPitch(midi: Int, velocity: Int) {

let channel = UInt32(0)
let noteCommand = UInt32(0x90 | channel)
Expand All @@ -285,16 +285,16 @@ class AudioUnitMIDISynth: NSObject {

status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
AudioUtils.CheckError(status)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), 64, 0)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
AudioUtils.CheckError(status)
}

/// Send a note off message using patch2 on channel 0
func stopPitch(midi: Int) {
func stopPitch(midi: Int, velocity: Int) {
let channel = UInt32(0)
let noteCommand = UInt32(0x80 | channel)
var status = OSStatus(noErr)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), 0, 0)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
AudioUtils.CheckError(status)
}

Expand Down
10 changes: 6 additions & 4 deletions ios/Classes/SwiftFlutterMidiPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ public class SwiftFlutterMidiPlugin: NSObject, FlutterPlugin {
case "play_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
au.playPitch(midi: midi ?? 60)
let velocity = _arguments["velocity"] as? Int
au.playPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Playing: \(String(describing: midi!))"
result(message)
case "stop_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
au.stopPitch(midi: midi ?? 60)
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
let velocity = _arguments["velocity"] as? Int
au.stopPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Stopped: \(String(describing: midi!))"
result(message)
default:
Expand Down
26 changes: 20 additions & 6 deletions lib/flutter_midi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class FlutterMidi extends FlutterMidiPlatform {
return result;
}

/// Unmute the device temporarly even if the mute switch is on or toggled in settings.
/// Unmute the device temporarily even if the mute switch is on or toggled in settings.
@override
Future<String> unmute() async {
final String result = await _channel.invokeMethod('unmute');
Expand All @@ -54,16 +54,30 @@ class FlutterMidi extends FlutterMidiPlatform {

/// Use this when stopping the sound onTouchUp or to cancel a long file.
/// Not needed if playing midi onTap.
/// Stop with velocity in the range between 0-127
@override
Future<String?> stopMidiNote({required int midi}) async {
return _channel.invokeMethod('stop_midi_note', {'note': midi});
Future<String?> stopMidiNote({
required int midi,
int velocity = 64,
}) async {
return _channel.invokeMethod('stop_midi_note', {
'note': midi,
'velocity': velocity,
});
}

/// Play a midi note from the sound_font.SF2 library bundled with the application.
/// Play a midi note in the range between 0-256
/// Play a midi note in the range between 0-127
/// Play with velocity in the range between 0-127
/// Multiple notes can be played at once as separate calls.
@override
Future<String?> playMidiNote({required int midi}) async {
return _channel.invokeMethod('play_midi_note', {'note': midi});
Future<String?> playMidiNote({
required int midi,
int velocity = 64,
}) async {
return _channel.invokeMethod('play_midi_note', {
'note': midi,
'velocity': velocity,
});
}
}
16 changes: 13 additions & 3 deletions lib/src/method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,30 @@ class MethodChannelUrlLauncher extends FlutterMidiPlatform {

/// Use this when stopping the sound onTouchUp or to cancel a long file.
/// Not needed if playing midi onTap.
/// Stop with velocity in the range between 0-127
@override
Future<String?> stopMidiNote({
required int midi,
int velocity = 64,
}) {
return _channel.invokeMethod<String>('stop_midi_note', {'note': midi});
return _channel.invokeMethod<String>('stop_midi_note', {
'note': midi,
'velocity': velocity,
});
}

/// Play a midi note from the sound_font.SF2 library bundled with the application.
/// Play a midi note in the range between 0-256
/// Play a midi note in the range between 0-127
/// Play with velocity in the range between 0-127
/// Multiple notes can be played at once as separate calls.
@override
Future<String?> playMidiNote({
required int midi,
int velocity = 64,
}) {
return _channel.invokeMethod<String>('play_midi_note', {'note': midi});
return _channel.invokeMethod<String>('play_midi_note', {
'note': midi,
'velocity': velocity,
});
}
}
10 changes: 7 additions & 3 deletions lib/src/platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,28 @@ class FlutterMidiPlatform extends PlatformInterface {
throw UnimplementedError('changeSound() has not been implemented.');
}

/// Unmute the device temporarly even if the mute switch is on or toggled in settings.
/// Unmute the device temporarily even if the mute switch is on or toggled in settings.
Future<String?> unmute() async {
throw UnimplementedError('canLaunch() has not been implemented.');
}

/// Use this when stopping the sound onTouchUp or to cancel a long file.
/// Not needed if playing midi onTap.
/// Stop with velocity in the range between 0-127
Future<String?> stopMidiNote({
required int midi,
int velocity = 64,
}) async {
throw UnimplementedError('stopMidiNote() has not been implemented.');
}

/// Play a midi note from the sound_font.SF2 library bundled with the application.
/// Play a midi note in the range between 0-256
/// Multiple notes can be played at once as seperate calls.
/// Play a midi note in the range between 0-127
/// Play with velocity in the range between 0-127
/// Multiple notes can be played at once as separate calls.
Future<String?> playMidiNote({
required int midi,
int velocity = 64,
}) async {
throw UnimplementedError('playMidiNote() has not been implemented.');
}
Expand Down
8 changes: 4 additions & 4 deletions macos/Classes/AudioUnitMIDISynth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ class AudioUnitMIDISynth: NSObject {
//

/// Send a note on message using patch2 on channel 0
func playPitch(midi: Int) {
func playPitch(midi: Int, velocity: Int) {

let channel = UInt32(0)
let noteCommand = UInt32(0x90 | channel)
Expand All @@ -285,16 +285,16 @@ class AudioUnitMIDISynth: NSObject {

status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
// AudioUtils.CheckError(status)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), 64, 0)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
// AudioUtils.CheckError(status)
}

/// Send a note off message using patch2 on channel 0
func stopPitch(midi: Int) {
func stopPitch(midi: Int, velocity: Int) {
let channel = UInt32(0)
let noteCommand = UInt32(0x80 | channel)
var status = OSStatus(noErr)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), 0, 0)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
// AudioUtils.CheckError(status)
}

Expand Down
10 changes: 6 additions & 4 deletions macos/Classes/FlutterMidiPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ public class FlutterMidiPlugin: NSObject, FlutterPlugin {
case "play_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
au.playPitch(midi: midi ?? 60)
let velocity = _arguments["velocity"] as? Int
au.playPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Playing: \(String(describing: midi!))"
result(message)
case "stop_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
au.stopPitch(midi: midi ?? 60)
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
let velocity = _arguments["velocity"] as? Int
au.stopPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Stopped: \(String(describing: midi!))"
result(message)
default:
Expand Down

0 comments on commit d4a3977

Please sign in to comment.