質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

0回答

649閲覧

Swift AVAudioEngine で読み込んだ音声から、左右のスピーカーのそれぞれの出力のボリュームを任意に変更した音声をファイルに保存したい

Ayasata

総合スコア0

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2022/05/01 11:28

バージョン情報など
Xcode: Version 13.3.1 (13E500a)
実機: iPhone6s

AVAudioEngine を使用して、エフェクトをかけた音声をファイルに保存する処理を作成しています。
以下のコードのように AVAudioPlayerNode と AVAudioUnitReverb を接続しており、
AVAudioPlayerNode では .pan を、AVAudioUnitReverb では .wetDryMix をそれぞれスライダで変更できるようにしました。

Swift

1import UIKit 2import AVFoundation 3 4// ViewController 5class ViewController: UIViewController { 6 // UI 7 let engine = AVAudioEngine() 8 let playerNode = AVAudioPlayerNode() 9 let reverbNode = AVAudioUnitReverb() 10 let slider1 = UISlider() 11 let slider2 = UISlider() 12 13 // ビューのロード時に呼ばれる 14 override func viewDidLoad() { 15 super.viewDidLoad() 16 17 do { 18 // slider1(wetDryMix 変更用スライダ) 19 slider1.frame = CGRect(x: 10, y: 50, width: 250, height: 40) 20 slider1.addTarget(self, action: #selector(slide1(_:)), for: .valueChanged) 21 slider1.maximumValue = 100 22 slider1.minimumValue = 0.0 23 slider1.setValue(0.0, animated: false) 24 self.view.addSubview(slider1) 25 26 // slider2(パン(音像定位) 変更用スライダ) 27 slider2.frame = CGRect(x: 10, y: 100, width: 250, height: 40) 28 slider2.addTarget(self, action: #selector(slide2(_:)), for: .valueChanged) 29 slider2.maximumValue = 1.0 30 slider2.minimumValue = -1.0 31 slider2.setValue(0.0, animated: false) 32 self.view.addSubview(slider2) 33 34 // 音ファイルの読み込み 35 var url: URL! 36 if UserDefaults.standard.object(forKey: "converted1" ) as? Bool == nil{ 37 UserDefaults.standard.set( true, forKey: "converted1" ) 38 url = URL(fileURLWithPath: Bundle.main.path(forResource: "original", ofType: "mp3")!) 39 }else{ 40 url = URL(fileURLWithPath: fileInDocumentsDirectory(filename: "changed.wav")) 41 } 42 let file = try AVAudioFile(forReading: url) 43 44 45 // Playerノードの準備 46 engine.attach(playerNode) 47 48 // reverbノードの準備 49 reverbNode.loadFactoryPreset(.largeChamber) // どの部屋かを指定できる 50 reverbNode.wetDryMix = 0.0 51 engine.attach(reverbNode) 52 53 // 接続 54 engine.connect(playerNode, to: reverbNode, format: file.processingFormat) 55 engine.connect(reverbNode, to: engine.mainMixerNode, format: file.processingFormat) 56 57 // 音ファイルの再生の準備 58 playerNode.scheduleFile(file, at: nil, completionCallbackType: .dataPlayedBack){ [self] _ in // 再生完了時に呼ばれる 59 reverbNode.removeTap(onBus: 0) // 書き込み終了の合図 60 } 61 62 // 開始 63 try engine.start() 64 playerNode.play() 65 66 // ファイルに書き込み 67 if UserDefaults.standard.object(forKey: "converted2" ) as? Bool == nil{ 68 UserDefaults.standard.set( true, forKey: "converted2" ) 69 // 書き込み先ファイルの作成 70 let url2 = URL(fileURLWithPath: fileInDocumentsDirectory(filename: "changed.wav")) 71 let outputFile = try! AVAudioFile(forWriting: url2, settings: playerNode.outputFormat(forBus: 0).settings) 72 73 reverbNode.installTap(onBus: 0, bufferSize: AVAudioFrameCount(reverbNode.outputFormat(forBus: 0).sampleRate), format: reverbNode.outputFormat(forBus: 0)) { (buffer, when) in 74 do { 75 try outputFile.write(from: buffer) 76 } catch let error { 77 print(error) 78 } 79 } 80 } 81 } catch { 82 print(error.localizedDescription) 83 } 84 } 85 86 // wetDryMix の変更スライダ 87 @objc func slide1(_ sender: UISlider) { 88 reverbNode.wetDryMix = sender.value 89 } 90 91 // pan の変更スライダ 92 @objc func slide2(_ sender: UISlider) { 93 playerNode.pan = sender.value 94 if abs(sender.value) >= 0.3{ 95 playerNode.volume = 3.0*abs(sender.value) 96 }else{ 97 playerNode.volume = 0.3 98 } 99 } 100 101 // fileURLを取得 102 func getDocumentsURL() -> NSURL { 103 let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL 104 return documentsURL 105 } 106 // ファイルのフルパスを作る 107 func fileInDocumentsDirectory(filename: String) -> String { 108 let fileURL = getDocumentsURL().appendingPathComponent(filename) 109 return fileURL!.path 110 } 111}

音声の再生の終了後、アプリを再起動するとエフェクトをかけたファイルが読み込まれます。
ここで、.wetDryMix の変更が保存した音声ファイルに反映されるのですが、.pan の変更は一切反映されませんでした。
以下、2点のいずれかについてご教授いただければと思います。

  1. .pan の変更設定を保存先のファイルに反映させる方法があれば教えてください。
    1. の方法以外で左右それぞれのスピーカーの音量の変更の設定を、音声ファイルとして保存する方法があれば教えてください。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問