从与Goertzel算法处理音频信号的结果 [英] Result from processing audio signal with Goertzel algorithm

查看:509
本文介绍了从与Goertzel算法处理音频信号的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个小信号处理应用程序。它处理在某些频率Goerztel算法音频信号(莫尔斯code)。应用程序保存临时文件到文件系统,录制结束后,开始检测信号。现在,我得到的结果与一群幅度。

I made a little signal processing app. It processes audio signal (morse code) on certain frequency with Goerztel algorithm. Application saves temporary file to the filesystem and after recording is finished, starts to detect signals. Now I got the result with bunch of magnitudes.

我真的不知道那些大小读什么。我该如何去$ C C不同于幅度莫尔斯code $?我该如何阅读?试图找到引用,但无处解释的结果是什么,以及如何阅读。

I don't really know what to read from those magnitudes. How can I decode the morse code from those magnitudes? How can I read them? Tried to find references, but nowhere is explained what is the result and how to read it.

编辑:

我的莫尔斯code应用程序是用Delphi和使用Windows Beep函数来发送信号,具有一定的频率。我使用的是1200赫兹信号。在像维基百科中描述的信号,单词和摩尔斯电哔声之间也暂停。所有这些都是准确的。

My morse code application is made with Delphi and uses Windows Beep function to send signals with certain frequency. I'm using 1200 Hz for signals. Also pauses between signals and words and morse beeps are like wikipedia described. All is accurate.

Goertzel.java:

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

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()));    
        }
    }

MorseDe coder.java:

MorseDecoder.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;
    }
}

EDIT2:

注意事项在处理样品的一些错误。更改code的while循环。

Notices some bugs in processing samples. Changed code in while loop.

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();
                }

问候, evilone

Regards, evilone

推荐答案

您的策尔过滤器会增加,当输出其通带内的一个基调是present,然后当音被删除下降。为了检测一个音调脉冲,例如莫尔斯code,你需要某种阈值检测器对过滤器,这将只是给了音present一个布尔值,在采样通过采样/语气不是present输出基础。尝试绘图输出值,一旦你看到它在图形化的形式,它应该是显而易见的。

The output of your Goertzel filter will increase when a tone within its passband is present, and then decrease when the tone is removed. In order to detect pulses of a tone, e.g. morse code, you need some kind of threshold detector on the output of the filter which will just give a boolean value for "tone present" / "tone not present" on a sample-by-sample basis. Try plotting the output values and it should be obvious once you see it in graphical form.

这篇关于从与Goertzel算法处理音频信号的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆