Ich muss eine Stereo-Audiodatei auf iOS wie folgt verarbeiten:
Was ich momentan habe ist:
%Vor%Der Effekt ist eine Unterklasse von AVAudioUnitEffect.
Ich habe Probleme, den Stereo-Eingang als Mono darzustellen und AVAudioPlayerNode für getrennte Kanäle auszugeben.
Ich habe versucht, die Lautstärke der PlayerNodes auf 0.5 zu setzen und auf -1.0 und 1.0 zu schwenken, aber da die Eingabe Stereo ist, liefert dies nicht die gewünschten Effekte.
Mit AVFoundation, ich denke, ich habe mindestens zwei Optionen: entweder ich ...
(1) Gleichen Sie die Kanäle für PlayerNodes aus, so dass beide PlayerNodes als Mono angezeigt werden. Danach könnte ich dieselbe Logik wie zuvor verwenden: Gleiche Lautstärke auf beiden PlayerNodes, andere Links und andere rechts und die Wirkung auf einen PlayerNode , nach MixerNode, wird der Effekt nur im rechten Ausgangskanal angezeigt.
(2) Behalten Sie die PlayerNodes als Stereo (Pan = 0.0), wenden Sie den Effekt nur auf einen PlayerNode an und weisen Sie dann den MixerNode an, die beiden Kanäle eines PlayerNodes als Quelle für den linken Kanal und die anderen Kanäle für den rechten Kanal zu verwenden . Ich nehme an, dann würde der MixerNode die Eingangskanäle effektiv entzerren, so dass er als Mono-Eingang erscheint und der Effekt nur von einem Ausgangskanal gehört werden kann.
Die Frage ist: Ist eine der oben genannten Strategien möglich und wie? Gibt es eine andere Option, die ich übersehen habe?
Ich verwende Swift für das Projekt, kann aber mit Objective-C zurechtkommen.
Nach dem Mangel an Antworten und meiner eigenen Forschung zu urteilen, scheint mir AVfoundation nicht der richtige Weg zu sein. Die Einfachheit mit AVFoundation ist verlockend, aber ich bin offen für Alternativen. Momentan forsche ich nach MTAudioProcessingTap
-classes und sie könnten nützlich sein. Hilfe wird immer noch geschätzt.
Ich habe mit zwei AVPlayern, die ich gleichzeitig spiele, das gewünschte Ergebnis erzielt. Ein AVPlayer hat eine Eingabe, die Audiodaten auf dem linken Kanal und Stille auf der rechten Seite gemittelt hat; und umgekehrt im anderen AVPlayer. Schließlich wird der Effekt nur auf eine AVPlayer-Instanz angewendet.
die proprietäre Wirkung auf eine AVPlayer Instanz Als Anwendung erwies sich als trivial zu sein, war die größte Hürde, wie die Stereo-Eingang entzerren.
Ich habe ein paar verwandte Fragen gefunden ( Schwenken eines Monosignals mit MultiChannelMixer und MTAudioProcessingTap , AVPlayer Wiedergabe von Einkanal-Audiostereo → mono ) und ein tutorial ( AVPlayer Audio mit MTAudioProcessingTap verarbeiten - auf das in fast allen anderen Tutorials, die ich versucht habe zu googlen, verwiesen wird, die alle darauf hindeuten, dass die Lösung wahrscheinlich darin liegt MTAudioProcessingTap.
Leider offizielle Dokumentation für MTAudioProcessing Hahn (oder einen anderen Aspekt von MediaToolbox) mehr oder weniger null. Ich meine, nur einige Beispielcode online gefunden wurde und die Header (MTAudioProcessingTap.h) durch Xcode. Aber mit dem oben genannten Tutorial ich es geschafft, zu starten.
Um die Dinge nicht zu einfach zu machen, entschied ich mich für Swift anstelle von Objective-C, in dem existierende Tutorials verfügbar waren. Das Konvertieren der Anrufe war nicht so schlimm und ich fand sogar fast fertige Beispiele zum Erstellen von MTAudioProcessingTap in Swift 2 . Ich habe es geschafft, mit der Verarbeitung von Taps zu beginnen und manipuliere leicht Audio damit (nun, ich könnte den Stream so ausgeben, wie er ist und ihn zumindest komplett auf Null stellen). Das Angleichen der Kanäle war jedoch eine Aufgabe für die Framework beschleunigen , nämlich die vDSP Teil davon.
Allerdings unter Verwendung von C-APIs, die extensiv Zeiger (typischen Fall: VDSP) verwenden, um mit Swift umständlich wird ziemlich schnell -mindestens Vergleich wie es mit Objective-C gemacht wird. Dies war auch ein Problem, als ich anfänglich MTAudioProcessingTaps in Swift schrieb: Ich konnte AudioTapContext ohne Fehler nicht weitergeben (in Obj-C ist der Kontext so einfach wie AudioTapContext *context = (AudioTapContext *)MTAudioProcessingTapGetStorage(tap);
) und alle UnsicherenMutablePointer haben mich glauben lassen, dass Swift nicht das ist richtiges Werkzeug für den Job.
Also habe ich Swift für die Verarbeitungsklasse aufgegeben und in Objective-C umstrukturiert.
Und wie bereits erwähnt, verwende ich zwei AVPlayer; Also in AudioPlayerController.swift habe ich:
Ich benutze "TapType", um die Kanäle zu unterscheiden und es ist (in Objective-C) so einfach definiert wie:
%Vor%MTAudioProcessingTap Callbacks werden in etwa so erstellt wie im Tutorial . Bei der Erstellung speichere ich den TapType jedoch in den Kontext, damit ich ihn in ProcessCallback überprüfen kann:
%Vor%Und schließlich geschieht das tatsächliche Gewichtheben in Prozessrückruf mit vDSP-Funktionen:
%Vor%Tags und Links objective-c ios avfoundation audio swift