私はプログラミングの初心者です。 私の学校のためにプロジェクトを作らなければなりません。目標は、マイクでレコーディングを行い、ハイパスフィルターをかけてm4aファイルに保存することです。swift 3 FFT音の周波数を取得m4a
このサイトと他の多くのサイトでは、同じコードが多数見つかりましたが、すぐに3のコードが到着するとコードは機能しなくなりました。
AVAudioPlayerでマイクから出てくるものを録音して保存することから始めます。
私はmpcバッファでファイルを読みました。
フロート配列のバッファからデータを取得します。
最後に、私が見つけた例のようにFFTを適用します。
バッファのデータ(バッファから来るフロートのテーブル)を表示すると、何かが含まれています。
私のVDSPベクトルを表示すると、データが含まれています。
しかし、私がFFTを適用すると、リールと虚数部を含むVDSP出力の結果が "ナノ"値を返します。
ここでは、FFTの機能を理解していないため、resutatの「出力」に周波数が含まれているかどうか、またはそれを含むVDSPのパラメータの1つだけの場合はわかりません。
次に、これらの結果にフィルタを適用し、変更を加えてm4aファイルを再構成するために値を逆FFTに戻すことを考えました。
私の方法が偽であるか、それは私のコードであれば
// recupere le lien du fichier audio a analysé
let url = getDocumentsDirectory().appendingPathComponent("recording.m4a")
// lancé l'audio dans le core AVaudioFile
let audioFile = try! AVAudioFile(forReading: url)
// nombre de frame dans l'audio
let frameCount = UInt32(audioFile.length)
print("frame count\(frameCount)")
//remplis un buffer avec les information du son et le nombre de framme
let buffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: frameCount)
do {
//lecture de l'audio dans le buffer
try audioFile.read(into: buffer, frameCount:frameCount)
print("lecture ok")
} catch {
//lecture échouer
}
print(buffer.floatChannelData?.pointee ?? "aucune valeur float")
// printer le buffer de byte de l'audio
print("\n buffer: \n");
for k in 1...frameCount
{
print("value buffer \(buffer.floatChannelData?.pointee[Int(k)])");
}
// définit un fonction log2n
let log2n = UInt(round(log2(Double(frameCount))))
// définit la taille de buffer final potentiel
let bufferSizePOT = Int(1 << log2n)
//crée une structure FFT
//Si zéro est renvoyé, la routine n'a pas réussi à allouer de stockage
let fftSetup = vDSP_create_fftsetup(log2n, Int32(kFFTRadix2))
//print fft
print("valeur du fftSetup \(fftSetup)")
// create packed real input
// séparation des buffer en nombre réel et imaginaire :
var realp = [Float](repeating: 0.0, count: bufferSizePOT/2)
var imagp = [Float](repeating: 0.0, count: bufferSizePOT/2)
/*
print("\n real and image: \n");
for k in 0..<realp.count
{
print("value real \(realp[k]) et value imaginaire \(imagp[k])");
}
*/
// construit un vecteur double contenant les real et les imaginaire
var output = DSPSplitComplex(realp: &realp, imagp: &imagp)
buffer.floatChannelData?.withMemoryRebound(to: DSPComplex.self, capacity: bufferSizePOT/2) {
/*
Copie le contenu d'un vecteur complexe intercalé C vers un vecteur complexe divisé Z; Précision unique.
void vDSP_ctoz(const DSPComplex *__C, vDSP_Stride __IC, const DSPSplitComplex *__Z, vDSP_Stride __IZ, vDSP_Length __N);
Paramètres
__C
Vecteur d'entrée complexe entrelacé à simple précision.
__IC
Stride pour C; Doit être un nombre pair.
__Z
Vecteur de sortie complexe à division simple.
za
Stride pour Z.
__N
Le nombre d'éléments à traiter.
*/
dspComplexStream in vDSP_ctoz(dspComplexStream, 2, &output, 1, UInt(bufferSizePOT/2))
}
/*
calcul la série de fourier discrette du domaine temporel ver le domaine fréquentielle
paramètre :
func vDSP_fft_zrip(_ __Setup:
- --FFTSetup: l'objet FFTsetup
_ __C: pointeur sur le vecteur complex de sortie
_ __IC: pas entre les elements de --C, (a 1 pour des meilleures performance)
_ __Log2N: Il base 2 exposant du nombre d'éléments à traiter. Par exemple, pour traiter 1024 éléments,
spécifiez 10 pour le paramètre Log2N.
_ __Direction: FFTDirection : donne la direction de la discretisations.
time domain to the frequency domain = (forward).
frequency domain to the time domain (inverse).
)*/
vDSP_fft_zrip(fftSetup!, &output, 1, log2n, Int32(FFTDirection(FFT_FORWARD)))
print("\nSpectrum:\n");
for i in 0..<realp.count
{
print("value de i \(i), réel : \(output.realp[i]), imaginaire : \(imagp[i])");
}
var fft = [Float](repeating:0.0, count:Int(bufferSizePOT/2))
let bufferOver2: vDSP_Length = vDSP_Length(bufferSizePOT/2)
vDSP_zvmags(&output, 1, &fft, 1, bufferOver2)
for i in 0..<bufferSizePOT/2
{
print("value de buff2 \(fft[i])");
}
// termine le processus FFT
vDSP_destroy_fftsetup(fftSetup)
そのEDIT場合、あなたは私に説明できる場合は、次のフィルタをローパスとジュスト遊び歌と
engine = AVAudioEngine()
player = AVAudioPlayerNode()
player.volume = 1.0
let path = Bundle.main.path(forResource: "audio10to1000", ofType: "wav")!
let url = NSURL.fileURL(withPath: path)
let file = try? AVAudioFile(forReading: url)
var mainMixer = AVAudioMixerNode()
mainMixer = engine.mainMixerNode
engine.attach(player)
EQNode = AVAudioUnitEQ(numberOfBands: 1)
var filterParams = EQNode.bands[0] as AVAudioUnitEQFilterParameters
filterParams.filterType = .lowPass
filterParams.frequency = 500.0
filterParams.bypass = false
engine.attach(EQNode)
engine.connect(player, to: EQNode, format: file?.processingFormat)
engine.connect(EQNode, to: mainMixer, format: file?.processingFormat)
// engine.connect(player, to: mainMixer, format: file?.processingFormat)
player.scheduleFile(file!, at: nil, completionHandler: nil)
engine.prepare()
do {
try engine.start()
} catch _ {
print("******************* erreur *************")
}
player.play()
:
は、この典型的なフィルタ応答from Wikipediaを参照してください。 'AVAudioUnitEQ'のためのGoogle。あなた自身で実装したい場合は、まずFIRまたはIIRソリューションに進んでください:https://en.wikipedia.org/wiki/Low-pass_filter楽しいことを! – shallowThought
hiii ご協力いただきありがとうございます。私はAVAudioUnitEQを使用するのに苦労しました。それがmixernodeで使用するすべてのエフェクト(例のスピッチ)はうまく動作します。 Eqノードは機能しません。それは私のコードです: 3日後には何もしません... –
変更することはありません...あなたの助けをもう一度お願いします 私は理解していることを確かめてください。 500Hzのローパスフィルタを使用するとき。私のオーディオが10hzで始まり10hで1000hzで終了する生成用の曲であれば、半分の時間でもう何も聞こえませんか? EQのgainGlobalを変更すると、filterParamsのゲインは変わりません。 –