Я разрабатываю приложение React Native, которое получает аудиоданные PCM через WebSocket, декодирует их из строки base64 и пытается воспроизвести их в реальном времени, используя настройку AVAudioEngine в Swift. Несмотря на подтверждение того, что аудиоданные получены правильно путем записи в файл и его воспроизведения в Audacity, воспроизведение в моем приложении представляет собой только шум. Я не могу определить причину.
Код JavaScript:
const handleAudioOutput = async (event) => {
const arrayBuffer = event.data;
const base64Data = Buffer.from(arrayBuffer).toString('base64');
// await RNFS.appendFile(`${RNFS.DocumentDirectoryPath}/audioData.raw`, base64Data, 'base64');
audioPlayer.current.playAudioData(base64Data);
};
useEffect(() => {
audioOutputWs.current = new WebSocket(audioOutputUrl);
audioOutputWs.current.onopen = () => console.log("Audio output ws open");
audioOutputWs.current.binaryType = 'arraybuffer';
audioOutputWs.current.onmessage = handleAudioOutput;
}, []);
На быстрой стороне мы буферизуем полученный звук и воспроизводим из буфера в другом потоке.
Реализация на быстрой стороне:
import Foundation
import AVFoundation
@objc(AudioPlayer)
class AudioPlayer: NSObject {
private var audioEngine: AVAudioEngine
private var audioPlayerNode: AVAudioPlayerNode
private var audioFormat: AVAudioFormat
private var audioQueue: [Data]
private let queueLock = NSLock()
private var isProcessing = false
override init() {
audioEngine = AVAudioEngine()
audioPlayerNode = AVAudioPlayerNode()
// Try using a common sample rate and format
let sampleRate: Double = 24000.0
let channelCount: AVAudioChannelCount = 1
let commonFormat: AVAudioCommonFormat = .pcmFormatInt16
guard let format = AVAudioFormat(commonFormat: commonFormat, sampleRate: sampleRate, channels: channelCount, interleaved: false) else {
fatalError("Failed to create AVAudioFormat")
}
audioFormat = format
audioQueue = []
super.init()
audioEngine.attach(audioPlayerNode)
// If I did format: audioFormat the constructor would crash So I found the below solution from some corner of the internet.
audioEngine.connect(audioPlayerNode, to: audioEngine.outputNode, format: AVAudioFormat.init(standardFormatWithSampleRate: 24000.0, channels: 1)!)
do {
try audioEngine.start()
} catch {
print("Failed to start AVAudioEngine: \(error)")
}
DispatchQueue.global(qos: .background).async {
self.processAudioQueue()
}
}
@objc(multiply:withB:withResolver:withRejecter:)
func multiply(a: Float, b: Float, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
resolve(a * b)
}
@objc(add:withB:withResolver:withRejecter:)
func add(a: Float, b: Float, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
resolve(a + b)
}
@objc(playAudioData:withResolver:withRejecter:)
func playAudioData(base64String: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
guard let data = Data(base64Encoded: base64String) else {
reject("error", "Invalid base64 string", nil)
return
}
queueLock.lock()
audioQueue.append(data)
queueLock.unlock()
resolve(true) // Immediately resolve to not block the JS thread
}
private func processAudioQueue() {
isProcessing = true
while isProcessing {
queueLock.lock()
if !audioQueue.isEmpty {
let data: Data = audioQueue.removeFirst()
queueLock.unlock()
let frameCount = AVAudioFrameCount(data.count / MemoryLayout.size)
guard let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: frameCount) else {
continue
}
audioBuffer.frameLength = frameCount
// Safe memory transfer using buffer pointers
data.withUnsafeBytes { rawBufferPointer in
guard let bufferPointer = rawBufferPointer.bindMemory(to: Int16.self).baseAddress else {
return
}
guard let channelData = audioBuffer.int16ChannelData else {
return
}
for frameIndex in 0..
Подробнее здесь: https://stackoverflow.com/questions/787 ... -websocket
Во время воспроизведения аудиоданных PCM, передаваемых через WebSocket, в React Native и Swift наблюдается только шум ⇐ IOS
Программируем под IOS
1720723220
Anonymous
Я разрабатываю приложение React Native, которое получает аудиоданные PCM через WebSocket, декодирует их из строки base64 и пытается воспроизвести их в реальном времени, используя настройку AVAudioEngine в Swift. Несмотря на подтверждение того, что аудиоданные получены правильно путем записи в файл и его воспроизведения в Audacity, воспроизведение в моем приложении представляет собой только шум. Я не могу определить причину.
Код JavaScript:
const handleAudioOutput = async (event) => {
const arrayBuffer = event.data;
const base64Data = Buffer.from(arrayBuffer).toString('base64');
// await RNFS.appendFile(`${RNFS.DocumentDirectoryPath}/audioData.raw`, base64Data, 'base64');
audioPlayer.current.playAudioData(base64Data);
};
useEffect(() => {
audioOutputWs.current = new WebSocket(audioOutputUrl);
audioOutputWs.current.onopen = () => console.log("Audio output ws open");
audioOutputWs.current.binaryType = 'arraybuffer';
audioOutputWs.current.onmessage = handleAudioOutput;
}, []);
На быстрой стороне мы буферизуем полученный звук и воспроизводим из буфера в другом потоке.
Реализация на быстрой стороне:
import Foundation
import AVFoundation
@objc(AudioPlayer)
class AudioPlayer: NSObject {
private var audioEngine: AVAudioEngine
private var audioPlayerNode: AVAudioPlayerNode
private var audioFormat: AVAudioFormat
private var audioQueue: [Data]
private let queueLock = NSLock()
private var isProcessing = false
override init() {
audioEngine = AVAudioEngine()
audioPlayerNode = AVAudioPlayerNode()
// Try using a common sample rate and format
let sampleRate: Double = 24000.0
let channelCount: AVAudioChannelCount = 1
let commonFormat: AVAudioCommonFormat = .pcmFormatInt16
guard let format = AVAudioFormat(commonFormat: commonFormat, sampleRate: sampleRate, channels: channelCount, interleaved: false) else {
fatalError("Failed to create AVAudioFormat")
}
audioFormat = format
audioQueue = []
super.init()
audioEngine.attach(audioPlayerNode)
// If I did format: audioFormat the constructor would crash So I found the below solution from some corner of the internet.
audioEngine.connect(audioPlayerNode, to: audioEngine.outputNode, format: AVAudioFormat.init(standardFormatWithSampleRate: 24000.0, channels: 1)!)
do {
try audioEngine.start()
} catch {
print("Failed to start AVAudioEngine: \(error)")
}
DispatchQueue.global(qos: .background).async {
self.processAudioQueue()
}
}
@objc(multiply:withB:withResolver:withRejecter:)
func multiply(a: Float, b: Float, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
resolve(a * b)
}
@objc(add:withB:withResolver:withRejecter:)
func add(a: Float, b: Float, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
resolve(a + b)
}
@objc(playAudioData:withResolver:withRejecter:)
func playAudioData(base64String: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
guard let data = Data(base64Encoded: base64String) else {
reject("error", "Invalid base64 string", nil)
return
}
queueLock.lock()
audioQueue.append(data)
queueLock.unlock()
resolve(true) // Immediately resolve to not block the JS thread
}
private func processAudioQueue() {
isProcessing = true
while isProcessing {
queueLock.lock()
if !audioQueue.isEmpty {
let data: Data = audioQueue.removeFirst()
queueLock.unlock()
let frameCount = AVAudioFrameCount(data.count / MemoryLayout.size)
guard let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: frameCount) else {
continue
}
audioBuffer.frameLength = frameCount
// Safe memory transfer using buffer pointers
data.withUnsafeBytes { rawBufferPointer in
guard let bufferPointer = rawBufferPointer.bindMemory(to: Int16.self).baseAddress else {
return
}
guard let channelData = audioBuffer.int16ChannelData else {
return
}
for frameIndex in 0..
Подробнее здесь: [url]https://stackoverflow.com/questions/78737235/experiencing-only-noise-during-playback-of-pcm-audio-data-streamed-via-websocket[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия