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

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

ただいまの
回答率

88.91%

マイクから拾ったデータを波形データに変換するには

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 7,569

Jidousya_364

score 31

Swiftでマイクから拾った音を波形データに変換するさせるにはどうすればよいのでしょうか。

現在私がやっているのはAudioToolboxを使って、マイクからデータを拾うもので波型データを得る方法が調べてもSwift3で使えそうなサンプルが見つかりませんでした。

※追記
私がやろうとしているのはマイクから取得したデータをリアルタイムにFFTしたいと考えています

import UIKit
import AudioToolbox

private func AudioQueueInputCallback(
_ inUserData: UnsafeMutableRawPointer?,
inAQ: AudioQueueRef,
inBuffer: AudioQueueBufferRef,
inStartTime: UnsafePointer<AudioTimeStamp>,
inNumberPacketDescriptions: UInt32,
inPacketDescs: UnsafePointer<AudioStreamPacketDescription>?)
{
print(inBuffer) //出力されない
//ここが音声データ? 出力されない
}

class AudioViewController: UIViewController {

@IBOutlet weak var loudLabel: UILabel!

@IBOutlet weak var peakTextField: UITextField!
@IBOutlet weak var averageTextField: UITextField!

var queue: AudioQueueRef!
var timer: Timer!

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

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.stopUpdatingVolume()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

// MARK: - Internal methods
func startUpdatingVolume() {
// Set data format
var dataFormat = AudioStreamBasicDescription(
mSampleRate: 44100.0,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: AudioFormatFlags(kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked),
mBytesPerPacket: 2,
mFramesPerPacket: 1,
mBytesPerFrame: 2,
mChannelsPerFrame: 1,
mBitsPerChannel: 16,
mReserved: 0)

// Observe input level
var audioQueue: AudioQueueRef? = nil
var error = noErr
error = AudioQueueNewInput(
&dataFormat,
AudioQueueInputCallback,//充填完了時に呼ばれる?
UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
.none,
.none,
0,
&audioQueue)
if error == noErr {
self.queue = audioQueue
}
AudioQueueStart(self.queue, nil)

// Enable level meter
var enabledLevelMeter: UInt32 = 1
AudioQueueSetProperty(self.queue, kAudioQueueProperty_EnableLevelMetering, &enabledLevelMeter, UInt32(MemoryLayout<UInt32>.size))

self.timer = Timer.scheduledTimer(timeInterval: 0.5,
target: self,
selector: #selector(AudioViewController.detectVolume(_:)),
userInfo: nil,
repeats: true)
self.timer?.fire()
}

func stopUpdatingVolume()
{
// Finish observation
self.timer.invalidate()
self.timer = nil
AudioQueueFlush(self.queue)
AudioQueueStop(self.queue, false)
AudioQueueDispose(self.queue, true)
}

func detectVolume(_ timer: Timer)
{
// Get level
var levelMeter = AudioQueueLevelMeterState()
var propertySize = UInt32(MemoryLayout<AudioQueueLevelMeterState>.size)

AudioQueueGetProperty(
self.queue,
kAudioQueueProperty_CurrentLevelMeterDB,
&levelMeter,
&propertySize)

// Show the audio channel's peak and average RMS power.
self.peakTextField.text = "".appendingFormat("%.2f", levelMeter.mPeakPower)
self.averageTextField.text = "".appendingFormat("%.2f", levelMeter.mAveragePower)

// Show "LOUD!!" if mPeakPower is larger than -1.0
self.loudLabel.isHidden = (levelMeter.mPeakPower >= -1.0) ? false : true
}
}

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+1

波形データって、マイクから拾って取得した音声データのことじゃないんですか?
現在どんなコードでマイクからデータを拾っているかコードを提示して、
どんなデータを得たいか具体的に説明すれば、何かアドバイスできるかもしれません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/02/23 19:06

    何度もすいません

    AudioQueueInputCallbackの中の
    // Do nothing, because not recoding.
     の部分にprint文でiodateなどを出力させたのですが、何も表示されず
    自分で調べてみたりもしたのですがioDataなどが何を意味しているのか理解できませんでした

    クレクレくんのようなことで申し訳ないのですが、至急、教えて下さらないでしょうか

    キャンセル

  • 2017/02/23 23:52

    ioDataというのがどこから出てきたものかわかりませんが、
    AudioQueueInputCallbackの呼び出しパラメータの説明は
    Googleで「AudioQueueInputCallback」を検索すれば出てきます。
    https://developer.apple.com/reference/audiotoolbox/audioqueueinputcallback
    その中でAudioQueueBufferRefのinBufferに音声データが入っています。
    inBufferをSwiftでどのように参照したらいいかは
    http://tiny-wing.hatenablog.com/entry/2016/05/22/010902
    が参考になると思います。
    この記事より、
    inBuffer.memory.mAudioDataByteSize
    でデータサイズを取得でき、
    inBuffer.memory.mAudioData
    でデータ内容を取得できることがわかると思います。
    ただ、この記事はSwift2用なので、Swift3だとおそらく
    memoryでなくpointeeに変更しろと言われると思います。

    キャンセル

  • 2017/02/24 19:48

    inBufferの参照方法を見てみたのですが理解できませんでした。すみません。
    コードの方を追加しますので、見てくださると嬉しいです

    inBufferの参照方法がよくわかりませんでした


    キャンセル

+1

http://krr.blog.shinobi.jp/javafx_praxis/java%E3%81%A7%E9%9F%B3%E5%A3%B0%E6%B3%A2%E5%BD%A2%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B
イメージとしては上記ページが参考になるかと思います。

データを取得するには、参考とされているソースの元記事ページに記載されている通り、
AudioInputCallback を設定する必要があります。
http://blog.koogawa.com/entry/2016/04/17/133052

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

AppleのサンプルコードにaurioTouchという、
CoreAudioを使いマイク入力をFFTしOpenGLで描画するものがあります。
こちらはそのサンプルコードをObjCからswift3に移植したものです。

https://github.com/ooper-shlab/aurioTouch2.0-Swift

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/02/25 12:18

    audioTouchを見させてもらいましたが、すいません自分では理解できませんでした。

    func performRender(
    _ ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
    inTimeStamp: UnsafePointer<AudioTimeStamp>,
    inBufNumber: UInt32,
    inNumberFrames: UInt32,
    ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus
    {


    のioDataにマイクで撮った音の情報が入っているという認識でよろしいのでしょうか

    キャンセル

  • 2017/02/26 10:13

    ソースコメントを読んでいただければ分かりますが、その中のAudioUnitRender呼び出しでマイクの音を取得しています。

    キャンセル

+1

私も動作の確認をする必要があったので色々試しましたが、audio queue servicesでも音声のバッファを取得することはできましたよ。設定したAudioQueueInputCallbackに定期的にバッファが返ってきます。
参照されている記事のやり方だと必要な処理が足りないので動作していませんでした。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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