From 24e3a460cc3a401d9dc89d8835a5ce3b8997000f Mon Sep 17 00:00:00 2001 From: Alexander Demchuk Date: Mon, 26 Aug 2024 13:15:36 +0200 Subject: [PATCH] feat: make module unique by renaming it to ExpoPlayAudioStream --- README.md | 22 +++++++------- ...StreamModule.kt => ExpoPlayAudioStream.kt} | 4 +-- example/App.tsx | 12 ++++---- expo-module.config.json | 4 +-- ios/AudioController.swift | 20 ------------- ...am.podspec => ExpoPlayAudioStream.podspec} | 2 +- ...Module.swift => ExpoPlayAudioStream.swift} | 30 +++++++++---------- package.json | 6 ++-- ...Module.ts => ExpoPlayAudioStreamModule.ts} | 2 +- src/index.ts | 14 ++++----- 10 files changed, 48 insertions(+), 68 deletions(-) rename android/src/main/java/expo/modules/audiostream/{ExpoAudioStreamModule.kt => ExpoPlayAudioStream.kt} (99%) rename ios/{ExpoAudioStream.podspec => ExpoPlayAudioStream.podspec} (94%) rename ios/{ExpoAudioStreamModule.swift => ExpoPlayAudioStream.swift} (64%) rename src/{ExpoAudioStreamModule.ts => ExpoPlayAudioStreamModule.ts} (77%) diff --git a/README.md b/README.md index 448a12b..6209ced 100644 --- a/README.md +++ b/README.md @@ -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 🎯 @@ -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'; @@ -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); } @@ -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`: Streams a base64-encoded audio chunk in the RIFF format with 16 kHz, 16-bit, mono PCM encoding. - `setVolume(volume: number): Promise`: Sets the volume of the audio playback, where `volume` is a value between 0 and 100. @@ -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. @@ -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). \ No newline at end of file +The Expo Play Audio Stream module is licensed under the [MIT License](LICENSE). diff --git a/android/src/main/java/expo/modules/audiostream/ExpoAudioStreamModule.kt b/android/src/main/java/expo/modules/audiostream/ExpoPlayAudioStream.kt similarity index 99% rename from android/src/main/java/expo/modules/audiostream/ExpoAudioStreamModule.kt rename to android/src/main/java/expo/modules/audiostream/ExpoPlayAudioStream.kt index 4236a38..30ef32c 100644 --- a/android/src/main/java/expo/modules/audiostream/ExpoAudioStreamModule.kt +++ b/android/src/main/java/expo/modules/audiostream/ExpoPlayAudioStream.kt @@ -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, @@ -42,7 +42,7 @@ class ExpoAudioStreamModule : Module() { private var isPlaying = false override fun definition() = ModuleDefinition { - Name("ExpoAudioStream") + Name("ExpoAudioStreamKin") OnCreate { initializeAudioTrack() diff --git a/example/App.tsx b/example/App.tsx index ae8185f..2245378 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -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"; @@ -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); } diff --git a/expo-module.config.json b/expo-module.config.json index 1feccf9..a05e94d 100644 --- a/expo-module.config.json +++ b/expo-module.config.json @@ -1,9 +1,9 @@ { "platforms": ["ios", "android"], "ios": { - "modules": ["ExpoAudioStreamModule"] + "modules": ["ExpoPlayAudioStream"] }, "android": { - "modules": ["expo.modules.audiostream.ExpoAudioStreamModule"] + "modules": ["expo.modules.audiostream.ExpoPlayAudioStream"] } } diff --git a/ios/AudioController.swift b/ios/AudioController.swift index 1d7fd38..09a509e 100644 --- a/ios/AudioController.swift +++ b/ios/AudioController.swift @@ -14,8 +14,6 @@ public class AudioController { init() { do { - //try setupAudioComponentsAndStart() - // setupNotifications() } catch { print("Failed to init") } @@ -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) } @@ -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() @@ -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() @@ -360,8 +344,4 @@ public class AudioController { } } } - - // private func currentQueue() -> [(buffer: AVAudioPCMBuffer, promise: RCTPromiseResolveBlock)] { - // return self.isPlayingQueueA ? self.bufferQueueA : self.bufferQueueB - // } } diff --git a/ios/ExpoAudioStream.podspec b/ios/ExpoPlayAudioStream.podspec similarity index 94% rename from ios/ExpoAudioStream.podspec rename to ios/ExpoPlayAudioStream.podspec index c80ce1a..f02d1da 100644 --- a/ios/ExpoAudioStream.podspec +++ b/ios/ExpoPlayAudioStream.podspec @@ -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'] diff --git a/ios/ExpoAudioStreamModule.swift b/ios/ExpoPlayAudioStream.swift similarity index 64% rename from ios/ExpoAudioStreamModule.swift rename to ios/ExpoPlayAudioStream.swift index 558f58d..e3a438c 100644 --- a/ios/ExpoAudioStreamModule.swift +++ b/ios/ExpoPlayAudioStream.swift @@ -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 {} } } diff --git a/package.json b/package.json index 7e56953..7acaba2 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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": { diff --git a/src/ExpoAudioStreamModule.ts b/src/ExpoPlayAudioStreamModule.ts similarity index 77% rename from src/ExpoAudioStreamModule.ts rename to src/ExpoPlayAudioStreamModule.ts index 72a04c1..d0f75ef 100644 --- a/src/ExpoAudioStreamModule.ts +++ b/src/ExpoPlayAudioStreamModule.ts @@ -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'); diff --git a/src/index.ts b/src/index.ts index 42fa4fb..de478e2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,11 @@ -import ExpoAudioStreamModule from "./ExpoAudioStreamModule"; +import ExpoPlayAudioStreamModule from "./ExpoPlayAudioStreamModule"; -export class ExpoAudioStream { +export class ExpoPlayAudioStream { static async streamRiff16Khz16BitMonoPcmChunk( base64Chunk: string ): Promise { try { - return ExpoAudioStreamModule.streamRiff16Khz16BitMonoPcmChunk( + return ExpoPlayAudioStreamModule.streamRiff16Khz16BitMonoPcmChunk( base64Chunk ); } catch (error) { @@ -16,7 +16,7 @@ export class ExpoAudioStream { static async setVolume(volme: number): Promise { try { - return await ExpoAudioStreamModule.setVolume(volme); + return await ExpoPlayAudioStreamModule.setVolume(volme); } catch (error) { console.error(error); throw new Error(`Failed to set volume: ${error}`); @@ -25,7 +25,7 @@ export class ExpoAudioStream { static async pause(): Promise { try { - return await ExpoAudioStreamModule.pause(); + return await ExpoPlayAudioStreamModule.pause(); } catch (error) { console.error(error); throw new Error(`Failed to pause audio: ${error}`); @@ -34,7 +34,7 @@ export class ExpoAudioStream { static async start(): Promise { try { - return await ExpoAudioStreamModule.start(); + return await ExpoPlayAudioStreamModule.start(); } catch (error) { console.error(error); throw new Error(`Failed to start audio: ${error}`); @@ -43,7 +43,7 @@ export class ExpoAudioStream { static async stop(): Promise { try { - return await ExpoAudioStreamModule.stop(); + return await ExpoPlayAudioStreamModule.stop(); } catch (error) { console.error(error); throw new Error(`Failed to stop audio: ${error}`);