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

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

ただいまの
回答率

90.35%

  • Swift

    7641questions

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

  • Xcode

    4315questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

音楽ファイルからバイナリデータが出力できない

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 866

Jidousya_364

score 23

class ViewController: UIViewController {

    let fileManager = FileManager()
    var audioRecorder: AVAudioRecorder? //録音設定
    var audioPlayer: AVAudioPlayer?
    //var audioFile:AVAudioFile! //読み込んだオーディオファイルの情報を格納し保持する
    let fileName = "OTO1.mp3 "

    override func viewDidLoad() {
        super.viewDidLoad()
         self.setupAudioRecorder()
    }

    func audiostatas(sender: AnyObject) {

        //var audioClass = AudioDataClass(address:documentFilePath().path)
        var audioClass = AudioDataClass(address: Bundle.main.path(forResource: "0322", ofType: "wav")!)
        //読み込み
        audioClass.loadAudioData()

    }

    func pushRecordButton(sender: AnyObject) {
        audioRecorder?.record()
    }
    // 録音するファイルのパスを取得(録音時、再生時に参照)
    // swift2からstringByAppendingPathComponentが使えなくなったので少し面倒
    func documentFilePath()-> URL {
        let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask) as [NSURL]
        let dirURL = urls[0]
        return dirURL.appendingPathComponent(fileName)!
    }

    func setupAudioRecorder() {
        // 再生と録音機能をアクティブにする
        let session = AVAudioSession.sharedInstance()
        try! session.setCategory(AVAudioSessionCategoryPlayAndRecord)
        try! session.setActive(true)
        let recordSetting : [String : AnyObject] = [
            AVEncoderAudioQualityKey : AVAudioQuality.min.rawValue as AnyObject,
            AVEncoderBitRateKey : 16 as AnyObject,
            AVNumberOfChannelsKey: 2 as AnyObject,
            AVSampleRateKey: 44100.0 as AnyObject,
            AVLinearPCMIsBigEndianKey: true as AnyObject// ビックエンディアン
        ]
        do {
            try audioRecorder = AVAudioRecorder(url: self.documentFilePath() as URL, settings: recordSetting)
        } catch {
            print("初期設定でerror出たよ(-_-;)")
        }
    }

}
import Foundation
import AVFoundation

class AudioDataClass{

    //object for audio file
    var audioFile:AVAudioFile! //読み込んだオーディオファイルの情報を格納し保持する

    //buffer for PCM data 便宜上AVAudioPCMBuffer型の変数を用意
    //クラス外から実際にバイナリデータにアクセスする際はbufferプロパティを使う。
    var PCMBuffer:AVAudioPCMBuffer!

    // audio file address
    var address:String

    //オーディオのバイナリデータを格納するためのbuffer, マルチチャンネルに対応するため、二次元配列になっています。
    var buffer:[[Float]]! = Array<Array<Float>>()

    //オーディオデータの情報
    var samplingRate:Double?
    var nChannel:Int?
    var nframe:Int?

    //initializer
    init(address:String){
        self.address = address
    }


    func loadAudioData(){

        print(buffer)

        //create AVAudioFile
        //error handling do catch
        do{

            //オーディオファイルを読み込み、データをaudioFileに格納
            self.audioFile = try AVAudioFile(forReading: NSURL(fileURLWithPath: self.address) as URL)
            //get samplingRate
            self.samplingRate = self.audioFile.fileFormat.sampleRate
            //get channel
            self.nChannel = Int(self.audioFile.fileFormat.channelCount)

        }catch{
            //読み込み失敗
            print("Error : loading audio file \(self.address) failed.")
        }

        //もしオーディオファイル読み込みが成功していたら、バイナリデータを取得する
        if(self.audioFile != nil){

            //get frame length
            self.nframe = Int(self.audioFile.length)

            //allocate 割り振る
            self.PCMBuffer = AVAudioPCMBuffer(pcmFormat: self.audioFile.processingFormat, frameCapacity: AVAudioFrameCount(self.nframe!))

            //error handling
            do{
                //audioFileから、PCMBufferにバイナリデータを取得する
                try self.audioFile.read(into: self.PCMBuffer)

                //各チャンネル毎にバイナリデータをbufferに追加する
                for i in 0..<self.nChannel!{

                    let buf:[Float] = Array(UnsafeMutableBufferPointer(start:self.PCMBuffer.floatChannelData![i], count:self.nframe!))

                    self.buffer.append(buf)
                }

                for i in 0..<self.nChannel!{
                    for j in 0..<self.nframe!{
                        print(self.buffer[i][j])
                    }
                    print("")
                }
            }catch{
                print("loading audio data failed.")
            }
        }
    }


http://qiita.com/programanx1/items/8912e60843bd824d74ce
私はここのサイトを参考にしてAudioRecoderで録音したWAVE形式の音楽ファイルをloadAudioData内でバイナリデータを見ようと思ったのですが

 for i in 0..<self.nChannel!{
                    for j in 0..<self.nframe!{
                        print(self.buffer[i][j])
                    }
                    print("")
                }


self.audioFile = try AVAudioFile(forReading: NSURL(fileURLWithPath: self.address) as URL)

self.audioFile = try AVAudioFile(forReading: NSURL(fileURLWithPath: self.address) as URL,commonFormat: AVAudioCommonFormat.pcmFormatInt16,interleaved: true)
に書き換え、
for i in 0..<1{
for j in 0..<self.nframe!{
print(String(self.buffer[i][j], radix: 16))
}
}

出力されるデータが以下のような形になってしまうのですがこの値がバイナリデータなのでしょうか?
-0.00427246
-0.0166626
-0.0283508
-0.0391541
-0.0498657
-0.0618896
-0.0748596
-0.0875854
-0.0992737
-0.110352
-0.122406
-0.135529
-0.148499
-0.160095
-0.170746
-0.18161
-0.193207
-0.204956
-0.215881
-0.225922
-0.236664
-0.24823
-0.259766
-0.270142
-0.278961
-0.288513
-0.300049
-0.312592

追記
self.audioFile = try AVAudioFile(forReading: NSURL(fileURLWithPath: self.address) as URL)

self.audioFile = try AVAudioFile(forReading: NSURL(fileURLWithPath: self.address) as URL,commonFormat: AVAudioCommonFormat.pcmFormatInt16,interleaved: true)
に書き換えたところ

 for i in 0..<1{
            for j in 0..<self.nframe!{
                print(String(self.buffer[i][j], radix: 16))
            }
        }
}


-140,-546,-929,-1283,-1634,-2028
が出力され、

16進数になっていないのかなと思ったので変換したら

for i in 0..<1{
            for j in 0..<self.nframe!{
                print(String(self.buffer[i][j], radix: 16))
            }
        }
}


-8c,-222,-3a1,-503,-662,-7ec,-995,-b36
になりました

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

使ったことないので知りませんが、

 let buf:[Float] = Array(UnsafeMutableBufferPointer(start:self.PCMBuffer.floatChannelData[i], count:self.nframe!))

floatChannelDataで取得しているようなのでfloat値になっているのでしょう。
int16Channel​Dataint32Channel​Dataを使えば整数値で取得出来るような気がします。


今のままでも、このfloat値が±1.0だと仮定すると、

print(String(Int(self.buffer[i][j] * 0x8000), radix: 16))

こうすれば±0x8000で表示されてバイナリデータっぽくなりますw


【追記されたInt16のデータについて】

-0.00427246 * 0x8000 = -139.99996928 ≒ -140 = -0x008c
-0.0166626  * 0x8000 = -546.0000768  ≒ -546 = -0x0222
-0.0283508  * 0x8000 = -928.9990144  ≒ -929 = -0x03a1
(以下略)

floatだろうがInt16だろうが、スケールが違うだけで同じ値なのですよ。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/28 08:45

    そういうことでしたか
    では上の方が張っていくださったhttp://www.graffiti.jp/pc/p030506a.htmのような形式では取れないのでしょうか?

    キャンセル

  • 2017/03/28 08:52 編集

    16bitならInt16でいいと思いますが。8bitならInt16の上位バイトだけ使えばいいです。

    あと、どうでもいいことですが、並べ替え出来るので「上の方」って書くのは無意味です。
    きちんと名前で書きましょう。

    キャンセル

  • 2017/03/28 09:31 編集

    Houraijilcさんの貼ってくださったものといったほうがよかったですね
    ありがとうございました。自分の求めるものができなさそうなのでもう一度質問させていただきます 

    キャンセル

+2

wavファイルデータの様なので、バイナリーではなく、リニアPCMのfloat値と思われます。

WAVEファイルの構造

で、ヘッダと16,24,32bit音声データの配置を把握して、
16,24,32bit音声データの「符号」「指数」「仮数」を把握して、
バイナリエディタで見れば、合ってるかどうかが分かります。
16,24bitの「符号」「指数」「仮数」はどこかで、探してみてください。

32bitについて、興味深い記事(?)がありましたので、URLを記しておきます。

第572回:ハイレゾで注目の「32bit-float」で、オーディオの常識が変わる?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

バイナリデータが何を意味するのか分かりませんが、質問者さんがみているのは、
リニアPCMの32bit float値([-1.0, 1.0])です。

AVAudioFileクラスの

public init(forReading fileURL: URL) throws


のコメントにこう書かれています。

/* This opens the file for reading using the standard format (deinterleaved floating point). */


standard format(floating point)とは、リニアPCMの32bit floatのことです。

AVAudioFileはフォーマットのコンバーターを内蔵しています。
指定したファイルがmp3,aif,wavなんであろうと、ビット数が16,24,32どれであろうと、
init(forReading fileURL:URL)で初期化すると、

open func read(into buffer: AVAudioPCMBuffer) throws


で読み出したデータは勝手に変換されてリニアPCMの32bit floatになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

AVAudioFileはフォーマットのコンバーターを内蔵しています。

とのことなので、
swiftでバイナリファイルの読み書きを行いたい
で、ファイルを読み、先の、ヘッダー情報から、wavのリニアPCMのバイト数を判断して、音声データを、バイナリーで読めば良いと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Swift

    7641questions

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

  • Xcode

    4315questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。