基于我在GitHub上的previous question和pitch detector。我设法检测出我的样本有哪些主要频率。但是就像Zaph所说的那样,切断整个样本将是无用的。我的问题是,是否已经将样本从时域转换到频域,那么我该如何返回并将频域转换到时域?
我的进场时间->频率
ConvertInt16ToFloat(THIS, dataBuffer, outputBufferFrequency, bufferCapacity);
maxFrames = 32;
log2n = log2f(maxFrames);
n = 1 << log2n;
assert(n == maxFrames);
nOver2 = maxFrames/2;
bufferCapacity = maxFrames;
COMPLEX_SPLIT A;
A.realp = (float *)malloc(nOver2 * sizeof(float));
A.imagp = (float *)malloc(nOver2 * sizeof(float));
fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2);
// Carry out a Forward FFT transform.
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
// The output signal is now in a split real form. Use the vDSP_ztoc to get
// a split real vector.
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2);
// Determine the dominant frequency by taking the magnitude squared and
// saving the bin which it resides in.
float dominantFrequency = 0;
int bin = -1;
for (int i=0; i<n; i+=2) {
float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]);
if (curFreq > dominantFrequency) {
dominantFrequency = curFreq;
bin = (i+1)/2;
}
}
更新
//First faild approach to convert frequency->ti
vDSP_ctoz((COMPLEX*)outputBufferFrequency, 2, &A, 1, nOver2);
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);
vDSP_ztoc(&A, 1, (COMPLEX *)outputBufferFrequency, 2, nOver2);
ConvertFloatToInt16(THIS, outputBufferFrequency, outputBufferTime, bufferCapacity);
// checking is preTimeToFrequency buffer is same as postTimeToFrequency buffer
// and is not, atm.
for (int i=0; i<bufferCapacity; i++) {
printf("%i != %i",((SInt16*)dataBuffer)[i], ((SInt16*)outputBufferTime)[i]);
if (((SInt16*)dataBuffer)[i] != ((SInt16*)outputBufferTime)[i]){
printf("dupa\n");
}
}
void ConvertInt16ToFloat(RIOInterface* THIS, void *buf, float *outputBuf, size_t capacity) {
AudioConverterRef converter;
OSStatus err;
size_t bytesPerSample = sizeof(float);
AudioStreamBasicDescription outFormat = {0};
outFormat.mFormatID = kAudioFormatLinearPCM;
outFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
outFormat.mBitsPerChannel = 8 * bytesPerSample;
outFormat.mFramesPerPacket = 1;
outFormat.mChannelsPerFrame = 1;
outFormat.mBytesPerPacket = bytesPerSample * outFormat.mFramesPerPacket;
outFormat.mBytesPerFrame = bytesPerSample * outFormat.mChannelsPerFrame;
outFormat.mSampleRate = THIS->sampleRate;
const AudioStreamBasicDescription inFormat = THIS->streamFormat;
UInt32 inSize = capacity*sizeof(SInt16);
UInt32 outSize = capacity*sizeof(float);
err = AudioConverterNew(&inFormat, &outFormat, &converter);
err = AudioConverterConvertBuffer(converter, inSize, buf, &outSize, outputBuf);
}
void ConvertFloatToInt16(RIOInterface* dev, float *buf, void *outputBuf, size_t capacity) {
AudioConverterRef converter;
OSStatus err;
size_t bytesPerSample = sizeof(short);
AudioStreamBasicDescription outFormat = {0};
outFormat.mFormatID = kAudioFormatLinearPCM;
outFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
outFormat.mBitsPerChannel = 8 * bytesPerSample;
outFormat.mFramesPerPacket = 1;
outFormat.mChannelsPerFrame = 1;
outFormat.mBytesPerPacket = bytesPerSample * outFormat.mFramesPerPacket;
outFormat.mBytesPerFrame = bytesPerSample * outFormat.mChannelsPerFrame;
outFormat.mSampleRate = dev->sampleRate;
const AudioStreamBasicDescription inFormat = dev->streamFormat;
UInt32 inSize = capacity*sizeof(float);
UInt32 outSize = capacity*sizeof(SInt16);
err = AudioConverterNew(&inFormat, &outFormat, &converter);
err = AudioConverterConvertBuffer(converter, inSize, buf, &outSize, outputBuf);
}
更新2
阅读this示例代码后的第二种方法
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);
vDSP_ztoc(&A, 1, (COMPLEX *)outputBufferFrequency, 2, nOver2);
float scale = 0.5/maxFrames;
vDSP_vsmul(outputBufferFrequency, 1, &scale, outputBufferFrequency, 1, maxFrames);
ConvertFloatToInt16(THIS, outputBufferFrequency, outputBufferTime, bufferCapacity);
解决了
最后!阅读this anwser之后,阅读一些示例代码,我设法弄清了我的问题。
我的工作代码。
ConvertInt16ToFloat(THIS, dataBuffer, outputBufferFrequency, bufferCapacity);
//TIME -> FREQUENCU
vDSP_ctoz((COMPLEX*)outputBufferFrequency, 2, &A, 1, nOver2);
// Carry out a Forward FFT transform.
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
// The output signal is now in a split real form. Use the vDSP_ztoc to get
// a split real vector.
vDSP_ztoc(&A, 1, (COMPLEX *)outputBufferFrequency, 2, nOver2);
//FREQUENCY -> TIME
//Back to time domain
vDSP_ctoz((COMPLEX*)outputBufferFrequency, 2, &A, 1, nOver2);
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);
float scale = (float) 1.0 / (2 * maxFrames);;
vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2);
vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2);
vDSP_ztoc(&A, 1, (COMPLEX *)outputBufferFrequency, 2, nOver2);
ConvertFloatToInt16(THIS, outputBufferFrequency, outputBufferTime, bufferCapacity);
void ConvertInt16ToFloat(RIOInterface* THIS, void *buf, float *outputBuf, size_t capacity) {
AudioConverterRef converter;
OSStatus err;
size_t bytesPerSample = sizeof(float);
AudioStreamBasicDescription outFormat = {0};
outFormat.mFormatID = kAudioFormatLinearPCM;
outFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
outFormat.mBitsPerChannel = 8 * bytesPerSample;
outFormat.mFramesPerPacket = 1;
outFormat.mChannelsPerFrame = 1;
outFormat.mBytesPerPacket = bytesPerSample * outFormat.mFramesPerPacket;
outFormat.mBytesPerFrame = bytesPerSample * outFormat.mChannelsPerFrame;
outFormat.mSampleRate = THIS->sampleRate;
THIS->streamFloatFormat = outFormat;
const AudioStreamBasicDescription inFormat = THIS->streamFormat;
UInt32 inSize = capacity*sizeof(SInt16);
UInt32 outSize = capacity*sizeof(float);
err = AudioConverterNew(&inFormat, &outFormat, &converter);
err = AudioConverterConvertBuffer(converter, inSize, buf, &outSize, outputBuf);
}
void ConvertFloatToInt16(RIOInterface* THIS, float *buf, void *outputBuf, size_t capacity) {
AudioConverterRef converter;
OSStatus err;
AudioStreamBasicDescription asbd = {0};
size_t bytesPerSample;
bytesPerSample = sizeof(SInt16);
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
asbd.mBitsPerChannel = 8 * bytesPerSample;
asbd.mFramesPerPacket = 1;
asbd.mChannelsPerFrame = 1;
asbd.mBytesPerPacket = bytesPerSample * asbd.mFramesPerPacket;
asbd.mBytesPerFrame = bytesPerSample * asbd.mChannelsPerFrame;
asbd.mSampleRate = sampleRate;
THIS->streamFormat = asbd;
const AudioStreamBasicDescription outFormat = THIS->streamFormat;
const AudioStreamBasicDescription inFormat = THIS->streamFloatFormat;
UInt32 inSize = capacity*sizeof(float);
UInt32 outSize = capacity*sizeof(SInt16);
err = AudioConverterNew(&inFormat, &outFormat, &converter);
err = AudioConverterConvertBuffer(converter, inSize, buf, &outSize, outputBuf);
}
最佳答案
逆傅立叶变换会将离散信号从频域变换回时域。
您可以像这样执行傅立叶逆变换-
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);
然后必须对其进行相应缩放。比例因子位于
图2-6 Apple在vDSP Programming Guide中发现的比例因子汇总
可以在这里找到一个很好的示例Forward and Inverse FFT using Accelerate。
同样,在阅读更新后,如果您尝试在频域中对信号进行音高偏移,然后再将其转换回时域,则涉及的内容还很多。我可以建议阅读DSP Dimension上有关Pitch shifting using the Fourier transform的文章。
关于ios - 从频域到时域,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21905798/