Skip to content

Commit

Permalink
feat: make module unique by renaming it to ExpoPlayAudioStream
Browse files Browse the repository at this point in the history
  • Loading branch information
demchuk-alex committed Aug 26, 2024
1 parent 33d45a1 commit 24e3a46
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 68 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Expo Audio Stream 🎶
# Expo Play Audio Stream 🎶

The Expo Audio Stream module is a powerful tool for streaming audio data in your Expo-based React Native applications. It provides a seamless way to play audio chunks in real-time, allowing you to build audio-centric features like voice assistants, audio players, and more.
The Expo Play Audio Stream module is a powerful tool for streaming audio data in your Expo-based React Native applications. It provides a seamless way to play audio chunks in real-time, allowing you to build audio-centric features like voice assistants, audio players, and more.

## Motivation 🎯

Expand All @@ -11,7 +11,7 @@ Expo's built-in audio capabilities are limited to playing pre-loaded audio files
Here's an example of how you can use the Expo Audio Stream module to play a sequence of audio chunks:

```javascript
import { ExpoAudioStream } from 'expo-audio-stream';
import { ExpoPlayAudioStream } from 'expo-audio-stream';

// Assuming you have some audio data in base64 format
const sampleA = 'base64EncodedAudioDataA';
Expand All @@ -20,14 +20,14 @@ const sampleB = 'base64EncodedAudioDataB';
useEffect(() => {
async function playAudioChunks() {
try {
await ExpoAudioStream.setVolume(100);
await ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
await ExpoPlayAudioStream.setVolume(100);
await ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
console.log('Streamed A');
await ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
await ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
console.log('Streamed B');
console.log('Streaming A & B');
ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
} catch (error) {
console.error(error);
}
Expand All @@ -39,7 +39,7 @@ useEffect(() => {

## API 📚

The Expo Audio Stream module provides the following API:
The Expo Play Audio Stream module provides the following API:

- `streamRiff16Khz16BitMonoPcmChunk(base64Chunk: string): Promise<void>`: Streams a base64-encoded audio chunk in the RIFF format with 16 kHz, 16-bit, mono PCM encoding.
- `setVolume(volume: number): Promise<void>`: Sets the volume of the audio playback, where `volume` is a value between 0 and 100.
Expand All @@ -57,7 +57,7 @@ The Kotlin implementation of the Expo Audio Stream module uses the `AudioTrack`

## Limitations and Considerations ⚠️

- The Expo Audio Stream module is designed to work with specific audio formats (RIFF, 16 kHz, 16-bit, mono PCM). If your audio data is in a different format, you may need to convert it before using the module.
- The Expo Play Audio Stream module is designed to work with specific audio formats (RIFF, 16 kHz, 16-bit, mono PCM). If your audio data is in a different format, you may need to convert it before using the module.
- The module does not provide advanced features like audio effects, mixing, or recording. It is primarily focused on real-time audio streaming.
- The performance of the module may depend on the device's hardware capabilities and the complexity of the audio data being streamed.

Expand All @@ -67,4 +67,4 @@ Contributions to the Expo Audio Stream module are welcome! If you encounter any

## License 📄

The Expo Audio Stream module is licensed under the [MIT License](LICENSE).
The Expo Play Audio Stream module is licensed under the [MIT License](LICENSE).
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext

class ExpoAudioStreamModule : Module() {
class ExpoPlayAudioStreamModule : Module() {
data class ChunkData(val chunk: String, val promise: Promise) // contains the base64 chunk
data class AudioChunk(
val audioData: FloatArray,
Expand All @@ -42,7 +42,7 @@ class ExpoAudioStreamModule : Module() {
private var isPlaying = false

override fun definition() = ModuleDefinition {
Name("ExpoAudioStream")
Name("ExpoAudioStreamKin")

OnCreate {
initializeAudioTrack()
Expand Down
12 changes: 6 additions & 6 deletions example/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { StyleSheet, Text, View } from "react-native";
import { ExpoAudioStream } from "@mykin-ai/expo-audio-stream";
import { ExpoPlayAudioStream } from "@mykin-ai/expo-audio-stream";
import { useEffect } from "react";
import { sampleA } from "./samples/sample-a";
import { sampleB } from "./samples/sample-b";
Expand All @@ -8,14 +8,14 @@ export default function App() {
useEffect(() => {
async function run() {
try {
await ExpoAudioStream.setVolume(100);
await ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
await ExpoPlayAudioStream.setVolume(100);
await ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
console.log("streamed A");
await ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
await ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
console.log("streamed B");
console.log("streaming A & B");
ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
ExpoAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleA);
ExpoPlayAudioStream.streamRiff16Khz16BitMonoPcmChunk(sampleB);
} catch (error) {
console.error(error);
}
Expand Down
4 changes: 2 additions & 2 deletions expo-module.config.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"platforms": ["ios", "android"],
"ios": {
"modules": ["ExpoAudioStreamModule"]
"modules": ["ExpoPlayAudioStream"]
},
"android": {
"modules": ["expo.modules.audiostream.ExpoAudioStreamModule"]
"modules": ["expo.modules.audiostream.ExpoPlayAudioStream"]
}
}
20 changes: 0 additions & 20 deletions ios/AudioController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ public class AudioController {

init() {
do {
//try setupAudioComponentsAndStart()
// setupNotifications()
} catch {
print("Failed to init")
}
Expand Down Expand Up @@ -93,10 +91,7 @@ public class AudioController {
NotificationCenter.default.addObserver(self, selector: #selector(handleMediaServicesWereLost), name: AVAudioSession.mediaServicesWereLostNotification, object: audioSession)
NotificationCenter.default.addObserver(self, selector: #selector(handleMediaServicesWereReset), name: AVAudioSession.mediaServicesWereResetNotification, object: audioSession)
NotificationCenter.default.addObserver(self, selector: #selector(audioSessionDidChangeFocus), name: AVAudioSession.silenceSecondaryAudioHintNotification, object: AVAudioSession.sharedInstance())


NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(appWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)

}
Expand Down Expand Up @@ -200,9 +195,6 @@ public class AudioController {
try? deactivateAudioSession()
}

// MARK: - Playback controls


private func safePause() {
if let node = audioPlayerNode, let engine = audioEngine, engine.isRunning {
node.pause()
Expand Down Expand Up @@ -337,14 +329,6 @@ public class AudioController {
return
}

// self.isPlayingQueueA.toggle() // Switch queues
//
// let currentQueue = self.currentQueue()
// for (buffer, promise) in currentQueue {
// self.audioPlayerNode!.scheduleBuffer(buffer) {
// promise(nil)
// }
// }
self.bufferAccessQueue.async {
if let (buffer, promise) = self.bufferQueue.first {
self.bufferQueue.removeFirst()
Expand All @@ -360,8 +344,4 @@ public class AudioController {
}
}
}

// private func currentQueue() -> [(buffer: AVAudioPCMBuffer, promise: RCTPromiseResolveBlock)] {
// return self.isPlayingQueueA ? self.bufferQueueA : self.bufferQueueB
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ require 'json'
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))

Pod::Spec.new do |s|
s.name = 'ExpoAudioStream'
s.name = 'ExpoPlayAudioStream'
s.version = package['version']
s.summary = package['description']
s.description = package['description']
Expand Down
30 changes: 15 additions & 15 deletions ios/ExpoAudioStreamModule.swift → ios/ExpoPlayAudioStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,40 @@ import Foundation
import AVFoundation
import ExpoModulesCore

public class ExpoAudioStreamModule: Module {
private let audioContoller = AudioController()
public class ExpoPlayAudioStreamModule: Module {
private let audioController = AudioController()

public func definition() -> ModuleDefinition {
Name("ExpoAudioStream")
Name("ExpoPlayAudioStream")

AsyncFunction("streamRiff16Khz16BitMonoPcmChunk") { (base64chunk: String, promise: Promise) in
audioContoller.streamRiff16Khz16BitMonoPcmChunk(base64chunk, resolver: { _ in
audioController.streamRiff16Khz16BitMonoPcmChunk(base64chunk, resolver: { _ in
promise.resolve(nil)
}, rejecter: { code, message, error in
promise.reject(code ?? "ERR_UNKNOWN", message ?? "Unknown error")
})
}

AsyncFunction("setVolume") { (volume: Float, promise: Promise) in
audioContoller.setVolume(volume, resolver: { _ in
audioController.setVolume(volume, resolver: { _ in
promise.resolve(nil)
}, rejecter: { code, message, error in
promise.reject(code ?? "ERR_VOLUME_ERROR", message ?? "Error setting volume")
})
}

AsyncFunction("pause") { promise in
audioContoller.pause(promise: promise)
audioController.pause(promise: promise)
}

AsyncFunction("play") { promise in
audioContoller.play(promise: promise)
audioController.play(promise: promise)
}

AsyncFunction("stop") { promise in
audioContoller.stop(promise: promise)
audioController.stop(promise: promise)
}

OnCreate {}
}
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mykin-ai/expo-audio-stream",
"version": "0.1.24",
"description": "Expo Audio Stream module",
"description": "Expo Play Audio Stream module",
"main": "build/index.js",
"types": "build/index.d.ts",
"source": "src/index.ts",
Expand All @@ -20,8 +20,8 @@
"keywords": [
"react-native",
"expo",
"expo-audio-stream",
"ExpoAudioStream"
"expo-play-audio-stream",
"ExpoPlayAudioStream"
],
"repository": "https://github.com/mykin-ai/expo-audio-stream",
"bugs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import { requireNativeModule } from 'expo-modules-core';

// It loads the native module object from the JSI or falls back to
// the bridge module (from NativeModulesProxy) if the remote debugger is on.
export default requireNativeModule('ExpoAudioStream');
export default requireNativeModule('ExpoPlayAudioStream');
14 changes: 7 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import ExpoAudioStreamModule from "./ExpoAudioStreamModule";
import ExpoPlayAudioStreamModule from "./ExpoPlayAudioStreamModule";

export class ExpoAudioStream {
export class ExpoPlayAudioStream {
static async streamRiff16Khz16BitMonoPcmChunk(
base64Chunk: string
): Promise<void> {
try {
return ExpoAudioStreamModule.streamRiff16Khz16BitMonoPcmChunk(
return ExpoPlayAudioStreamModule.streamRiff16Khz16BitMonoPcmChunk(
base64Chunk
);
} catch (error) {
Expand All @@ -16,7 +16,7 @@ export class ExpoAudioStream {

static async setVolume(volme: number): Promise<void> {
try {
return await ExpoAudioStreamModule.setVolume(volme);
return await ExpoPlayAudioStreamModule.setVolume(volme);
} catch (error) {
console.error(error);
throw new Error(`Failed to set volume: ${error}`);
Expand All @@ -25,7 +25,7 @@ export class ExpoAudioStream {

static async pause(): Promise<void> {
try {
return await ExpoAudioStreamModule.pause();
return await ExpoPlayAudioStreamModule.pause();
} catch (error) {
console.error(error);
throw new Error(`Failed to pause audio: ${error}`);
Expand All @@ -34,7 +34,7 @@ export class ExpoAudioStream {

static async start(): Promise<void> {
try {
return await ExpoAudioStreamModule.start();
return await ExpoPlayAudioStreamModule.start();
} catch (error) {
console.error(error);
throw new Error(`Failed to start audio: ${error}`);
Expand All @@ -43,7 +43,7 @@ export class ExpoAudioStream {

static async stop(): Promise<void> {
try {
return await ExpoAudioStreamModule.stop();
return await ExpoPlayAudioStreamModule.stop();
} catch (error) {
console.error(error);
throw new Error(`Failed to stop audio: ${error}`);
Expand Down

0 comments on commit 24e3a46

Please sign in to comment.