gpt4 book ai didi

android - 使用 Goertzel 算法处理音频信号的结果

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:32:24 26 4
gpt4 key购买 nike

我制作了一个小的信号处理应用程序。它使用 Goerztel 算法处理一定频率的音频信号(摩尔斯电码)。应用程序将临时文件保存到文件系统,录制完成后,开始检测信号。现在我得到了很多数量级的结果。

我真的不知道从这些量级可以看出什么。我怎样才能从这些幅度解码莫尔斯电码?我怎样才能阅读它们?试图找到引用资料,但没有任何地方解释结果是什么以及如何阅读。

编辑:

我的摩尔斯电码应用程序是用 Delphi 制作的,使用 Windows Beep 功能以一定的频率发送信号。我使用 1200 Hz 的信号。信号和单词之间的停顿以及莫尔斯哔哔声也像维基百科描述的那样。一切都是准确的。

Goertzel.java:

 public class Goertzel {

private float samplingRate;
private float targetFrequency;
private int n;

private double coeff, Q1, Q2;
private double sine, cosine;

public Goertzel(float samplingRate, float targetFrequency, int inN) {
this.samplingRate = samplingRate;
this.targetFrequency = targetFrequency;
n = inN;

sine = Math.sin(2 * Math.PI * (targetFrequency / samplingRate));
cosine = Math.cos(2 * Math.PI * (targetFrequency / samplingRate));
coeff = 2 * cosine;
}

public void resetGoertzel() {
Q1 = 0;
Q2 = 0;
}

public void initGoertzel() {
int k;
float floatN;
double omega;

floatN = (float) n;
k = (int) (0.5 + ((floatN * targetFrequency) / samplingRate));
omega = (2.0 * Math.PI * k) / floatN;
sine = Math.sin(omega);
cosine = Math.cos(omega);
coeff = 2.0 * cosine;

resetGoertzel();
}

public void processSample(double sample) {
double Q0;

Q0 = coeff * Q1 - Q2 + sample;
Q2 = Q1;
Q1 = Q0;
}

public double[] getRealImag(double[] parts) {
parts[0] = (Q1 - Q2 * cosine);
parts[1] = (Q2 * sine);

return parts;
}

public double getMagnitudeSquared() {
return (Q1 * Q1 + Q2 * Q2 - Q1 * Q2 * coeff);
}
}

SoundCompareActivity.java

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SoundCompareActivity extends Activity {

private static final int RECORDER_SAMPLE_RATE = 8000; // at least 2 times
// higher than sound
// frequency,
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

private AudioRecord recorder = null;
private int bufferSize = 0;
private Thread recordingThread = null;
private boolean isRecording = false;

private Button startRecBtn;
private Button stopRecBtn;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

startRecBtn = (Button) findViewById(R.id.button1);
stopRecBtn = (Button) findViewById(R.id.button2);

startRecBtn.setEnabled(true);
stopRecBtn.setEnabled(false);

bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLE_RATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);

startRecBtn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
Log.d("SOUNDCOMPARE", "Start Recording");

startRecBtn.setEnabled(false);
stopRecBtn.setEnabled(true);
stopRecBtn.requestFocus();

startRecording();
}
});

stopRecBtn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
Log.d("SOUNDCOMPARE", "Stop recording");

startRecBtn.setEnabled(true);
stopRecBtn.setEnabled(false);
startRecBtn.requestFocus();

stopRecording();
}
});
}

private void startRecording() {
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLE_RATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize);

recorder.startRecording();

isRecording = true;

recordingThread = new Thread(new Runnable() {

@Override
public void run() {
writeAudioDataToTempFile();
}
}, "AudioRecorder Thread");

recordingThread.start();
}

private String getTempFilename() {
File file = new File(getFilesDir(), "tempaudio");

if (!file.exists()) {
file.mkdirs();
}

File tempFile = new File(getFilesDir(), "signal.raw");

if (tempFile.exists())
tempFile.delete();

return (file.getAbsolutePath() + "/" + "signal.raw");
}

private void writeAudioDataToTempFile() {
byte data[] = new byte[bufferSize];
String filename = getTempFilename();
FileOutputStream os = null;

try {
os = new FileOutputStream(filename);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

int read = 0;

if (os != null) {
while (isRecording) {
read = recorder.read(data, 0, bufferSize);

if (read != AudioRecord.ERROR_INVALID_OPERATION) {
try {
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}

try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

private void deleteTempFile() {
File file = new File(getTempFilename());

file.delete();
}

private void stopRecording() {
if (recorder != null) {
isRecording = false;

recorder.stop();
recorder.release();

recorder = null;
recordingThread = null;
}

new MorseDecoder().execute(new File(getTempFilename()));
}
}

莫尔斯解码器.java:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.os.AsyncTask;
import android.util.Log;

public class MorseDecoder extends AsyncTask<File, Void, Void> {
private FileInputStream is = null;

@Override
protected Void doInBackground(File... files) {
int index;
//double magnitudeSquared;
double magnitude;

int bufferSize = AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);

Goertzel g = new Goertzel(8000, 1200, bufferSize);
g.initGoertzel();

for (int i = 0; i < files.length; i++) {
byte[] data = new byte[bufferSize];

try {
is = new FileInputStream(files[i]);

while(is.read(data) != -1) {
ShortBuffer sbuf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
short[] audioShorts = new short[sbuf.capacity()];
sbuf.get(audioShorts);

float[] audioFloats = new float[audioShorts.length];

for (int j = 0; j < audioShorts.length; j++) {
audioFloats[j] = ((float)audioShorts[j]) / 0x8000;
}

for (index = 0; index < audioFloats.length; index++) {
g.processSample(data[index]);
}

magnitude = Math.sqrt(g.getMagnitudeSquared());


Log.d("SoundCompare", "Relative magnitude = " + magnitude);

g.resetGoertzel();
}

is.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

return null;
}
}

编辑 2:

注意到处理示例中的一些错误。更改了 while 循环中的代码。

while(is.read(data) != -1) {
ShortBuffer sbuf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
short[] audioShorts = new short[sbuf.capacity()];
sbuf.get(audioShorts);

float[] audioFloats = new float[audioShorts.length];

for (int j = 0; j < audioShorts.length; j++) {
audioFloats[j] = ((float)audioShorts[j]) / 0x8000;
}

for (index = 0; index < audioFloats.length; index++) {
g.processSample(audioFloats[index]);

magnitude = Math.sqrt(g.getMagnitudeSquared());
Log.d("SoundCompare", "Relative magnitude = " + magnitude);
}

//magnitude = Math.sqrt(g.getMagnitudeSquared());


//Log.d("SoundCompare", "Relative magnitude = " + magnitude);

g.resetGoertzel();
}

问候,恶灵

最佳答案

你的 Goertzel filter 的输出当存在其通带内的音调时将增加,然后当音调被移除时减小。为了检测音调的脉冲,例如莫尔斯电码,您需要在滤波器的输出端使用某种阈值检测器,它将逐个样本地给出“音调存在”/“音调不存在”的 bool 值。尝试绘制输出值,一旦以图形形式看到它应该很明显。

关于android - 使用 Goertzel 算法处理音频信号的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7339763/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com