Skip to content
This repository has been archived by the owner on Dec 3, 2024. It is now read-only.

Commit

Permalink
Merge pull request #12 from niusounds/feature/0.2.0
Browse files Browse the repository at this point in the history
0.2.0
  • Loading branch information
niusounds authored Oct 31, 2021
2 parents ddd66cb + 24dcf73 commit 591ff00
Show file tree
Hide file tree
Showing 30 changed files with 222 additions and 1,457 deletions.
152 changes: 8 additions & 144 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ packets.collect { packet ->
Simply use `AudioTrackOutput` to play received audio.

```kotlin
val packets = receiveReaStream()
AudioTrackOutput().play(packets)
receiveReaStream().play(sampleRate = 48000) // sampleRate must be equal to input audio
```

If you want to play audio and process MIDI at the same time, use `SharedFlow`.
Expand All @@ -36,7 +35,7 @@ If you want to play audio and process MIDI at the same time, use `SharedFlow`.
coroutineScope {
val packets = receiveReaStream().shareIn(this, SharingStarted.WhileSubscribed())
launch {
AudioTrackOutput().play(packets)
packets.play(sampleRate = 48000)
}
launch {
packets.filter { it.isMidi }
Expand All @@ -53,7 +52,7 @@ coroutineScope {
## Send audio/MIDI to REAPER

```kotlin
val sampleRate = 44100 // Usually 44100 or 48000 is good choice.
val sampleRate = 48000 // Usually 44100 or 48000 is good choice.
val channels = 2 // Only 1 or 2 are currently supported.
val sender = ReaStreamSender(
identifier = "default", // Must be the same as REAPER
Expand All @@ -66,6 +65,10 @@ val sender = ReaStreamSender(
val data = byteArrayOf(0x90.toByte(), 60, 127)
sender.send(data)

// or something like
sender.send(midiData(MidiCommand.NoteOn, channel, noteNumber, velocity))
sender.send(midiData(MidiCommand.NoteOff, channel, noteNumber, velocity))

// send audio
val input = AudioRecordInput(
sampleRate = sampleRate,
Expand Down Expand Up @@ -108,145 +111,6 @@ repositories {
dependencies {
implementation 'com.github.niusounds:libReaStream:0.1.0' // Add this
implementation 'com.github.niusounds:libReaStream:0.2.0' // Add this
}
```

---

**Below this is the old API. These APIs are soon deleted in near future. So do not use anymore.**
### Receive audio from remote

For receiving audio and stream it to speaker, simply call `ReaStream.startReceiving()`:

```kotlin
val reaStream = ReaStream()
reaStream.startReceiving()

// After done
reaStream.stopReceiving()
```

Received audio will be routed to speaker output.

If you want to process audio packet rather than output to speaker, create class which implements `AudioPacketHandler` and `AudioPacketHandler.Factory`.

```kotlin
class MyAudioPacketHandler : AudioPacketHandler {
override fun process(channels: Int, sampleRate: Int, audioData: FloatArray, audioDataLength: Int) {
// This is called in background thread. Don't update UI directly here.
//
// audioData is filled from index 0 to audioDataLength - 1.
// Sample order is (N = audioDataLength / channels)
// [ch1-s1, ch1-s2, ch1-s3, ..., ch1-sN, ch2-s1, ch2-s2, ch2-s3, ..., ch2-sN]
//
// Typically channels will be 2 or 1. But ReaStream VST plugin supports up to 8 channels.
}

override fun release() {
// Do something on ReaStream.close() is called.
}
}

class MyAudioPacketHandlerFactory : AudioPacketHandler.Factory {
override fun create(): AudioPacketHandler = MyAudioPacketHandler()
}
```

Then pass `MyAudioPacketHandlerFactory` to `ReaStream`'s constructor.

```kotlin
val reaStream = ReaStream(audioPacketHandlerFactory = MyAudioPacketHandlerFactory())
```

### Send audio to remote

Use `ReaStream.startSending()` to send Android's microphone to remote.

```kotlin
// Specify your target machine's IP address.
// If ommitted, default send target is broadcast address.
reaStream.remoteAddress = InetAddress.getByName("192.168.10.10")
reaStream.startSending()

// After done
reaStream.stopSending()
```

If you stream other audio source, create class which implements `AudioStreamSource` and `AudioStreamSourceFactory`.

```kotlin
class MyAudioStreamSource : AudioStreamSource {
override read(): FloatBuffer {
// Return audio data.
// FloatBuffer must be filled with audio data starting at position 0 and set valid audio data length to [FloatBuffer.limit].
}

override fun release() {
// Do something on ReaStream.close() is called.
}
}

class MyAudioStreamSourceFactory : AudioStreamSource.Factory {
override fun create(): AudioStreamSource = MyAudioStreamSource()
}
```

Then pass `MyAudioStreamSourceFactory` to `ReaStream`'s constructor.

```kotlin
val reaStream = ReaStream(audioStreamSourceFactory = MyAudioStreamSourceFactory())
```

### Receive MIDI event from remote

If you want to handle MIDI event, create class which implements `MidiPacketHandler` and `MidiPacketHandler.Factory`.

```kotlin
class MyMidiPacketHandler : MidiPacketHandler {
override fun process(midiEvent: MidiEvent) {
// This is called in background thread. Don't update UI directly here.
}

override fun release() {
// Do something on ReaStream.close() is called.
}
}

class MyMidiPacketHandlerFactory : MidiPacketHandler.Factory {
override fun create(): MidiPacketHandler = MyMidiPacketHandler()
}
```

Then pass `MyMidiPacketHandlerFactory` to `ReaStream`'s constructor.

```kotlin
reaStream = ReaStream(midiPacketHandlerFactory = MidiHandlerFactory())
```

### Send MIDI event to remote

Currently, `ReaStream` does not support sending MIDI event. Instead, `ReaStreamSender` can be used to send MIDI event.

```kotlin
val sender = ReaStreamSender(remote = InetSocketAddress("192.168.1.2", ReaStream.DEFAULT_PORT))

// Send note on
sender.send(MidiEvent.create(MidiEvent.NOTE_ON, 0, noteNumber, 100))
// Send note off
sender.send(MidiEvent.create(MidiEvent.NOTE_OFF, 0, noteNumber, 0))

// After use
sender.close()
```

See *midisample* example app.


### Release resources

You must call `ReaStream.close()` if ReaStream is no more needed.

```kotlin
reaStream.close()
```
31 changes: 31 additions & 0 deletions docs/migrating_from_0.1_to_0.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## sampleRate

In 0.1, some classes implicitly use sample rate `44100` but default sample rate is not always 44100 in DAW. So I decided to remove default `sampleRate`.

From 0.2, some API takes `sampleRate`. You must specify appropriate value.

## AudioTrackOutput

`AudioTrackOutput` is replaced with `play()` function on `Flow<ReaStreamPacket>`.

```
// 0.1
val packets = receiveReaStream()
AudioTrackOutput().play(packets)
// 0.2
val packets = receiveReaStream()
packets.play(sampleRate = 48000) // sampleRate is required here
```

## Old APIs are removed

Almost all classes in `com.niusounds.libreastream.*` are removed so please migrate to `com.niusounds.libreastream.receiver.*` and `com.niusounds.libreastream.sender.*` before upgrading to 0.2.

## DatagramChannelReceiver and DatagramSocketReceiver

Both two classes are removed.

## ReaStreamReceiver

`ReaStreamReceiver` is removed. Use `receiveReaStream` function.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 591ff00

Please sign in to comment.