diff --git a/README.md b/README.md index 3463fe4e0..46cd0a830 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ check out the [Getting Started](https://docs.swmansion.com/react-native-audio-ap Simple ability to play and buffer audio, with all of the most commonly used functions, same as on the web, without the need to create and manipulate an audio graph. - **MIDI support 🎸**
- Complementary lib for react-native-audio-api, that will allow to communicate with MIDI devices or read/write MIDI files. + Complementary lib for react-native-audio-api, that will allow to communicate with MIDI devices. - **Spatial Audio 🛢️**
manipulate audio in 3D space diff --git a/apps/common-app/src/examples/Midi/Midi.tsx b/apps/common-app/src/examples/Midi/Midi.tsx new file mode 100644 index 000000000..200d13d00 --- /dev/null +++ b/apps/common-app/src/examples/Midi/Midi.tsx @@ -0,0 +1,118 @@ +import React, { JSX } from 'react'; +import { MIDIInput, requestMIDIAccess } from 'react-native-medi'; +import { Button, View, Text, ScrollView } from 'react-native'; +import { Container } from '../../components'; +import { colors } from '../../styles'; + + +function getColoredMidiMessage(data: Uint8Array): JSX.Element { + // Map MIDI message types to colors + // each message is 3 bytes: [status, data1, data2] + // statuses: + // 128, 135 - Note Off (red) + // 144, 151 - Note On (green) + // 176, 183 - Control Change (dark purple) + // others - default color + const status = data[0]; + const RED = '#FF5555'; + const GREEN = '#55FF55'; + const DARK_PURPLE = '#AA00AA'; + const DEFAULT_COLOR = '#AAAAAA'; // gray + + let color; + if (status >= 128 && status <= 135) { + color = RED; + } else if (status >= 144 && status <= 151) { + color = GREEN; + } else if (status >= 176 && status <= 183) { + color = DARK_PURPLE; + } else { + color = DEFAULT_COLOR; + } + + return {`${Array.from(data).join(', ')}`}; +} + +const Medi: React.FC = () => { + const [sourcePorts, setSourcePorts] = React.useState([]); + const [connectedPort, setConnectedPort] = React.useState(null); + const [messageLog, setMessageLog] = React.useState([]); + const scrollViewRef = React.useRef(null); + + const scanMIDIDevices = async () => { + const access = await requestMIDIAccess(); + setSourcePorts(access.inputs); + }; + + const connectToPort = async (portId: string) => { + if (connectedPort) { + await connectedPort.close(); + } + const access = await requestMIDIAccess(); + const input = access.inputs.find((port) => port.id === portId); + if (input) { + await input.open(); + input.onmidimessage = (message: Uint8Array) => { + setMessageLog((prevLog) => [...prevLog, getColoredMidiMessage(message)]); + }; + setConnectedPort(input); + console.log(`Connected to MIDI Input Port: ${portId}`); + } else { + console.log(`MIDI Input Port not found: ${portId}`); + setConnectedPort(null); + } + }; + + const disconnectPort = async () => { + if (connectedPort) { + await connectedPort.close(); + setConnectedPort(null); + setMessageLog([]); + console.log(`Disconnected from MIDI Input Port`); + } + } + + return ( + + + +