- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想捕获音频并将其转换为字节数组。
但是当我录制音频时,会添加噪音。
android中是否有任何过滤库,以便我可以去除其中的噪音。
问候,
斯内哈
最佳答案
使用下面的类来分析Audio,这里我给大家提供三个类。我已经使用此类来识别信号级别(音频 Db 级别)。我认为您可以了解如何过滤音频中的噪音。以下类使用 AudioRecoder 录制音频并将其转换为字节并测量信号强度。
音频分析器.java
package com.indianic.audioanalyzer;
import android.util.Log;
/**
* An {@link Instrument} which analyses an audio stream in various ways.
*
* <p>To use this class, your application must have permission RECORD_AUDIO.
*/
public class AudioAnalyser
{
// ******************************************************************** //
// Constructor.
// ******************************************************************** //
/**
* Create a WindMeter instance.
*
* @param parent Parent surface.
*/
public AudioAnalyser() {
audioReader = new AudioReader();
biasRange = new float[2];
}
// ******************************************************************** //
// Configuration.
// ******************************************************************** //
/**
* Set the sample rate for this instrument.
*
* @param rate The desired rate, in samples/sec.
*/
public void setSampleRate(int rate) {
sampleRate = rate;
}
/**
* Set the input block size for this instrument.
*
* @param size The desired block size, in samples. Typical
* values would be 256, 512, or 1024. Larger block
* sizes will mean more work to analyse the spectrum.
*/
public void setBlockSize(int size) {
inputBlockSize = size;
// Allocate the spectrum data.
spectrumData = new float[inputBlockSize / 2];
spectrumHist = new float[inputBlockSize / 2][historyLen];
}
/**
* Set the decimation rate for this instrument.
*
* @param rate The desired decimation. Only 1 in rate blocks
* will actually be processed.
*/
public void setDecimation(int rate) {
sampleDecimate = rate;
}
/**
* Set the histogram averaging window for this instrument.
*
* @param len The averaging interval. 1 means no averaging.
*/
public void setAverageLen(int len) {
historyLen = len;
// Set up the history buffer.
spectrumHist = new float[inputBlockSize / 2][historyLen];
spectrumIndex = 0;
}
// ******************************************************************** //
// Run Control.
// ******************************************************************** //
/**
* The application is starting. Perform any initial set-up prior to
* starting the application. We may not have a screen size yet,
* so this is not a good place to allocate resources which depend on
* that.
*/
public void appStart() {
}
/**
* We are starting the main run; start measurements.
*/
public void measureStart() {
audioProcessed = audioSequence = 0;
readError = AudioReader.Listener.ERR_OK;
audioReader.startReader(sampleRate, inputBlockSize * sampleDecimate, new AudioReader.Listener() {
@Override
public final void onReadComplete(short[] buffer) {
receiveAudio(buffer);
}
@Override
public void onReadError(int error) {
handleError(error);
}
});
}
/**
* We are stopping / pausing the run; stop measurements.
*/
public void measureStop() {
audioReader.stopReader();
}
/**
* The application is closing down. Clean up any resources.
*/
public void appStop() {
}
// ******************************************************************** //
// Audio Processing.
// ******************************************************************** //
/**
* Handle audio input. This is called on the thread of the audio
* reader.
*
* @param buffer Audio data that was just read.
*/
private final void receiveAudio(short[] buffer) {
// Lock to protect updates to these local variables. See run().
synchronized (this) {
audioData = buffer;
++audioSequence;
}
}
/**
* An error has occurred. The reader has been terminated.
*
* @param error ERR_XXX code describing the error.
*/
private void handleError(int error) {
synchronized (this) {
readError = error;
}
}
// ******************************************************************** //
// Main Loop.
// ******************************************************************** //
/**
* Update the state of the instrument for the current frame.
* This method must be invoked from the doUpdate() method of the
* application's {@link SurfaceRunner}.
*
* <p>Since this is called frequently, we first check whether new
* audio data has actually arrived.
*
* @param now Nominal time of the current frame in ms.
*/
public final void doUpdate() {
short[] buffer = null;
synchronized (this) {
if (audioData != null && audioSequence > audioProcessed) {
audioProcessed = audioSequence;
buffer = audioData;
}
}
// If we got data, process it without the lock.
if (buffer != null)
processAudio(buffer);
if (readError != AudioReader.Listener.ERR_OK)
processError(readError);
}
/**
* Handle audio input. This is called on the thread of the
* parent surface.
*
* @param buffer Audio data that was just read.
*/
private final void processAudio(short[] buffer) {
// Process the buffer. While reading it, it needs to be locked.
synchronized (buffer) {
// Calculate the power now, while we have the input
// buffer; this is pretty cheap.
final int len = buffer.length;
// If we have a power gauge, calculate the signal power.
setCurrentPower(SignalPower.calculatePowerDb(buffer, 0, len));
// If we have a spectrum analyser, set up the FFT input data.
Log.i(this.getClass().getSimpleName(), "dB = " + getCurrentPower() + "\t\t" + Math.round(getCurrentPower()));
// Tell the reader we're done with the buffer.
buffer.notify();
}
}
/**
* Handle an audio input error.
*
* @param error ERR_XXX code describing the error.
*/
private final void processError(int error) {
}
// ******************************************************************** //
// Class Data.
// ******************************************************************** //
public void setCurrentPower(double currentPower) {
this.currentPower = currentPower;
}
public double getCurrentPower() {
return currentPower;
}
// Debugging tag.
@SuppressWarnings("unused")
private static final String TAG = "instrument";
// The desired sampling rate for this analyser, in samples/sec.
private int sampleRate = 8000;
// Audio input block size, in samples.
private int inputBlockSize = 256;
// The desired decimation rate for this analyser. Only 1 in
// sampleDecimate blocks will actually be processed.
private int sampleDecimate = 1;
// The desired histogram averaging window. 1 means no averaging.
private int historyLen = 4;
// Our audio input device.
private final AudioReader audioReader;
// Buffered audio data, and sequence number of the latest block.
private short[] audioData;
private long audioSequence = 0;
// If we got a read error, the error code.
private int readError = AudioReader.Listener.ERR_OK;
// Sequence number of the last block we processed.
private long audioProcessed = 0;
// Analysed audio spectrum data; history data for each frequency
// in the spectrum; index into the history data; and buffer for
// peak frequencies.
private float[] spectrumData;
private float[][] spectrumHist;
private int spectrumIndex;
// Current signal power level, in dB relative to max. input power.
private double currentPower = 0f;
// Temp. buffer for calculated bias and range.
private float[] biasRange = null;
}
==================AudioReader.java
package com.indianic.audioanalyzer;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;
/**
* A class which reads audio input from the mic in a background thread and
* passes it to the caller when ready.
*
* <p>To use this class, your application must have permission RECORD_AUDIO.
*/
public class AudioReader
{
// ******************************************************************** //
// Public Classes.
// ******************************************************************** //
/**
* Listener for audio reads.
*/
public static abstract class Listener {
/**
* Audio read error code: no error.
*/
public static final int ERR_OK = 0;
/**
* Audio read error code: the audio reader failed to initialise.
*/
public static final int ERR_INIT_FAILED = 1;
/**
* Audio read error code: an audio read failed.
*/
public static final int ERR_READ_FAILED = 2;
/**
* An audio read has completed.
* @param buffer Buffer containing the data.
*/
public abstract void onReadComplete(short[] buffer);
/**
* An error has occurred. The reader has been terminated.
* @param error ERR_XXX code describing the error.
*/
public abstract void onReadError(int error);
}
// ******************************************************************** //
// Constructor.
// ******************************************************************** //
/**
* Create an AudioReader instance.
*/
public AudioReader() {
// audioManager = (AudioManager) app.getSystemService(Context.AUDIO_SERVICE);
}
// ******************************************************************** //
// Run Control.
// ******************************************************************** //
/**
* Start this reader.
*
* @param rate The audio sampling rate, in samples / sec.
* @param block Number of samples of input to read at a time.
* This is different from the system audio
* buffer size.
* @param listener Listener to be notified on each completed read.
*/
public void startReader(int rate, int block, Listener listener) {
Log.i(TAG, "Reader: Start Thread");
synchronized (this) {
// Calculate the required I/O buffer size.
int audioBuf = AudioRecord.getMinBufferSize(rate,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT) * 2;
// Set up the audio input.
audioInput = new AudioRecord(MediaRecorder.AudioSource.MIC,
rate,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
audioBuf);
inputBlockSize = block;
sleepTime = (long) (1000f / ((float) rate / (float) block));
inputBuffer = new short[2][inputBlockSize];
inputBufferWhich = 0;
inputBufferIndex = 0;
inputListener = listener;
running = true;
readerThread = new Thread(new Runnable() {
public void run() { readerRun(); }
}, "Audio Reader");
readerThread.start();
}
}
/**
* Stop this reader.
*/
public void stopReader() {
Log.i(TAG, "Reader: Signal Stop");
synchronized (this) {
running = false;
}
try {
if (readerThread != null)
readerThread.join();
} catch (InterruptedException e) {
;
}
readerThread = null;
// Kill the audio input.
synchronized (this) {
if (audioInput != null) {
audioInput.release();
audioInput = null;
}
}
Log.i(TAG, "Reader: Thread Stopped");
}
// ******************************************************************** //
// Main Loop.
// ******************************************************************** //
/**
* Main loop of the audio reader. This runs in our own thread.
*/
private void readerRun() {
short[] buffer;
int index, readSize;
int timeout = 200;
try {
while (timeout > 0 && audioInput.getState() != AudioRecord.STATE_INITIALIZED) {
Thread.sleep(50);
timeout -= 50;
}
} catch (InterruptedException e) { }
if (audioInput.getState() != AudioRecord.STATE_INITIALIZED) {
Log.e(TAG, "Audio reader failed to initialize");
readError(Listener.ERR_INIT_FAILED);
running = false;
return;
}
try {
Log.i(TAG, "Reader: Start Recording");
audioInput.startRecording();
while (running) {
long stime = System.currentTimeMillis();
if (!running)
break;
readSize = inputBlockSize;
int space = inputBlockSize - inputBufferIndex;
if (readSize > space)
readSize = space;
buffer = inputBuffer[inputBufferWhich];
index = inputBufferIndex;
synchronized (buffer) {
int nread = audioInput.read(buffer, index, readSize);
boolean done = false;
if (!running)
break;
if (nread < 0) {
Log.e(TAG, "Audio read failed: error " + nread);
readError(Listener.ERR_READ_FAILED);
running = false;
break;
}
int end = inputBufferIndex + nread;
if (end >= inputBlockSize) {
inputBufferWhich = (inputBufferWhich + 1) % 2;
inputBufferIndex = 0;
done = true;
} else
inputBufferIndex = end;
if (done) {
readDone(buffer);
// Because our block size is way smaller than the audio
// buffer, we get blocks in bursts, which messes up
// the audio analyzer. We don't want to be forced to
// wait until the analysis is done, because if
// the analysis is slow, lag will build up. Instead
// wait, but with a timeout which lets us keep the
// input serviced.
long etime = System.currentTimeMillis();
long sleep = sleepTime - (etime - stime);
if (sleep < 5)
sleep = 5;
try {
buffer.wait(sleep);
} catch (InterruptedException e) { }
}
}
}
} finally {
Log.i(TAG, "Reader: Stop Recording");
if (audioInput.getState() == AudioRecord.RECORDSTATE_RECORDING)
audioInput.stop();
}
}
/**
* Notify the client that a read has completed.
*
* @param buffer Buffer containing the data.
*/
private void readDone(short[] buffer) {
inputListener.onReadComplete(buffer);
}
/**
* Notify the client that an error has occurred. The reader has been
* terminated.
*
* @param error ERR_XXX code describing the error.
*/
private void readError(int code) {
inputListener.onReadError(code);
}
// ******************************************************************** //
// Class Data.
// ******************************************************************** //
// Debugging tag.
@SuppressWarnings("unused")
private static final String TAG = "WindMeter";
// ******************************************************************** //
// Private Data.
// ******************************************************************** //
// Our audio input device.
private AudioRecord audioInput;
// Our audio input buffer, and the index of the next item to go in.
private short[][] inputBuffer = null;
private int inputBufferWhich = 0;
private int inputBufferIndex = 0;
// Size of the block to read each time.
private int inputBlockSize = 0;
// Time in ms to sleep between blocks, to meter the supply rate.
private long sleepTime = 0;
// Listener for input.
private Listener inputListener = null;
// Flag whether the thread should be running.
private boolean running = false;
// The thread, if any, which is currently reading. Null if not running.
private Thread readerThread = null;
}
===================
信号电源.java
/**
* dsp: various digital signal processing algorithms
* <br>Copyright 2009 Ian Cameron Smith
*
* <p>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation (see COPYING).
*
* <p>This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package com.indianic.audioanalyzer;
/**
* A power metering algorithm.
*/
public final class SignalPower {
// ******************************************************************** //
// Constructor.
// ******************************************************************** //
/**
* Only static methods are provided in this class.
*/
private SignalPower() {
}
// ******************************************************************** //
// Algorithm.
// ******************************************************************** //
/**
* Calculate the bias and range of the given input signal.
*
* @param sdata Buffer containing the input samples to process.
* @param off Offset in sdata of the data of interest.
* @param samples Number of data samples to process.
* @param out A float array in which the results will be placed
* Must have space for two entries, which will be
* set to:
* <ul>
* <li>The bias, i.e. the offset of the average
* signal value from zero.
* <li>The range, i.e. the absolute value of the largest
* departure from the bias level.
* </ul>
* @throws NullPointerException Null output array reference.
* @throws ArrayIndexOutOfBoundsException Output array too small.
*/
public final static void biasAndRange(short[] sdata, int off, int samples,
float[] out)
{
// Find the max and min signal values, and calculate the bias.
short min = 32767;
short max = -32768;
int total = 0;
for (int i = off; i < off + samples; ++i) {
final short val = sdata[i];
total += val;
if (val < min)
min = val;
if (val > max)
max = val;
}
final float bias = (float) total / (float) samples;
final float bmin = min + bias;
final float bmax = max - bias;
final float range = Math.abs(bmax - bmin) / 2f;
out[0] = bias;
out[1] = range;
}
/**
* Calculate the power of the given input signal.
*
* @param sdata Buffer containing the input samples to process.
* @param off Offset in sdata of the data of interest.
* @param samples Number of data samples to process.
* @return The calculated power in dB relative to the maximum
* input level; hence 0dB represents maximum power,
* and minimum power is about -95dB. Particular
* cases of interest:
* <ul>
* <li>A non-clipping full-range sine wave input is
* about -2.41dB.
* <li>Saturated input (heavily clipped) approaches
* 0dB.
* <li>A low-frequency fully saturated input can
* get above 0dB, but this would be pretty
* artificial.
* <li>A really tiny signal, which only occasionally
* deviates from zero, can get below -100dB.
* <li>A completely zero input will produce an
* output of -Infinity.
* </ul>
* <b>You must be prepared to handle this infinite
* result and results greater than zero,</b> although
* clipping them off would be quite acceptable in
* most cases.
*/
public final static double calculatePowerDb(short[] sdata, int off, int samples) {
// Calculate the sum of the values, and the sum of the squared values.
// We need longs to avoid running out of bits.
double sum = 0;
double sqsum = 0;
for (int i = 0; i < samples; i++) {
final long v = sdata[off + i];
sum += v;
sqsum += v * v;
}
// sqsum is the sum of all (signal+bias)², so
// sqsum = sum(signal²) + samples * bias²
// hence
// sum(signal²) = sqsum - samples * bias²
// Bias is simply the average value, i.e.
// bias = sum / samples
// Since power = sum(signal²) / samples, we have
// power = (sqsum - samples * sum² / samples²) / samples
// so
// power = (sqsum - sum² / samples) / samples
double power = (sqsum - sum * sum / samples) / samples;
// Scale to the range 0 - 1.
power /= MAX_16_BIT * MAX_16_BIT;
// Convert to dB, with 0 being max power. Add a fudge factor to make
// a "real" fully saturated input come to 0 dB.
return Math.log10(power) * 10f + FUDGE;
}
// ******************************************************************** //
// Constants.
// ******************************************************************** //
// Maximum signal amplitude for 16-bit data.
private static final float MAX_16_BIT = 32768;
// This fudge factor is added to the output to make a realistically
// fully-saturated signal come to 0dB. Without it, the signal would
// have to be solid samples of -32768 to read zero, which is not
// realistic. This really is a fudge, because the best value depends
// on the input frequency and sampling rate. We optimise here for
// a 1kHz signal at 16,000 samples/sec.
private static final float FUDGE = 0.6f;
}
==============================
关于android - android中是否有任何声音过滤库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6042093/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!