概述
2012.07.16
spectrum
http://ldesoras.free.fr/prod.html
audacity
http://audacity.sourceforge.net/about/images/audacity-macosx.png
void audioStateChanged(QAudio::State state);
emit spectrumChanged(positionUs, lengthUs, spectrum);
分析 Spectrograph
spectrograph.h
QPair<qreal, qreal> barRange(int barIndex) const;
void selectBar(int index);
void updateBars();
void selectBar(int index);
1.取得当前的bar中位置根据鼠标点击,
2.动态画波形图
鼠标注册事件
可以根据文件SIZE 先画一个长度的文件。
, m_bufferDuration(0)
, m_recordPosition(0)
, m_playPosition(0)
, m_windowPosition(0)
, m_windowLength(0)
应该在connect 中有相关的内容
2012.07.17
QGraphicsItem
可以设置两 种形状
1。线波形
2。粗波形
根据buffer SIZE 确整个长度
QWT
http://blog.csdn.net/dongliqiang2006/article/details/5447410
Opengl
以上两 种科学绘图用,Unuse
2012.07.18
http://www.codeproject.com/Articles/6855/FFT-of-In-audio-signals
- FFT of waveIn audio signals
Qt audio spectrum
#include <QtMultimedia>
QT += multimedia
http://doc.qt.nokia.com/4.7-snapshot/demos-spectrum.html
FFTReal,
[教程] CMP最具特色功能之【MP3声音频谱】
http://shout-toolkit.sourceforge.net/classFFTReal.html
- Mac
- FFTReal is built as an OSX framework by adding the following to fftreal.pro:
CONFIG += lib_bundle
- The framework is then copied into the application bundle, and the paths embedded in the two binaries are updated using the install_name_tool command. This is done by the following code, in app.pro:
- framework_dir = ../spectrum.app/Contents/Frameworks
- framework_name = fftreal.framework/Versions/1/fftreal
- QMAKE_POST_LINK =
- mkdir -p $${framework_dir} &&\
- rm -rf $${framework_dir}/fftreal.framework &&\
- cp -R ../fftreal/fftreal.framework $${framework_dir} &&\
- install_name_tool -id @executable_path/../Frameworks/$${framework_name} \
- $${framework_dir}/$${framework_name} &&\
- install_name_tool -change $${framework_name} \
- @executable_path/../Frameworks/$${framework_name} \
- ../spectrum.app/Contents/MacOS/spectrum
- (flash 板本)晨风开发过一个叫cenfun mp3 mixer的东西,就是显示mp3混音频谱的这个混音频谱也就是CMP3乃至CMP4的声音频谱的原型
- 网上找了很多关于C++, QT图表,波形图,都关系到 FftReal (快速傅里叶变换和逆变换)
大家估计都比较熟悉,在MATLAB中比较容易录制一个短小的音频,然后对其进行处理。
比如wavrecord函数就可以胜任,然后使用wavplay就可以播放了。
但是我们经常看到很多音频处理软件,在录制音频的时候会同步显示录制音频的频谱图。
这个看似很简单的功能,可是在MATLAB中实现起来好像不容易哦。我想尽脑子都没有想出好的解决方法。
今天终于发现原来MATLAB的数据获取工具箱可以很轻松的帮忙解决这个问题。请看代码,注意运行程序需要有耳麦:
isRealTime=1; % 是否同步显示
Ai=analoginput('winsound'); % 创建一个模拟信号输入对象
% 添加通道
addchannel(Ai,1:2);
LastTime=10; % 采样时间
Ai.SampleRate=5000; % 采样频率
Ai.SamplesPerTrigger=Ai.SampleRate*LastTime; % 采样数
start(Ai); % 开启采样
if ~isRealTime % 判断是否同步
% 不同步
wait(Ai,LastTime+1); % 需要等待录制完
data=getdata(Ai); % 获取对象中的音频数据
plot(data); % 绘图了
else
% 同步
warning off % 当采样数据不够时,取消警告
while isrunning(Ai) % 检查对象是否仍在运行
data=peekdata(Ai,Ai.SampleRate); % 获取对象中的最后Ai.SampleRate个采样数据
plot(data) % 绘制最后Ai.SampleRate个采样数据的图形,因此表现出来就是实时的了
drawnow; % 刷新图像
end
warning on
end
stop(Ai); % 停止对象
delete(Ai); % 删除对象
原文:http://www.matlabsky.com/thread-9796-1-1.html
circlewidget svgviewer qmusicplayer /Developer/Examples/Qt/painting 2012.7.19 傅里叶变换在物理学、声学、光学、结构动力学、数论、组合数学、概率论、统计学、信号处理、密码学、海洋学、通讯等领域都有着广泛的应用。例如在信号处理中,傅里叶变换的典型用途是将信号分解成振幅分量和频率分量。 离散形式的傅里叶变换可以利用数字计算机快速的实现(其算法称为快速傅里叶变换算法(FFT))。 离散傅里叶变换 主条目:离散傅里叶变换 为了在科学计算和数字信号处理等领域使用计算机进行傅里叶变换,必须将函数xn定义在离散点而非连续域内,且须满足有限性或周期性条件。这种情况下,使用离散傅里叶变换,将函数xn表示为下面的求和形式:
其中是傅里叶振幅。直接使用这个公式计算的计算复杂度为,而快速傅里叶变换(FFT)可以将复杂度改进为。计算复杂度的降低以及数字电路计算能力的发展使得DFT成为在信号处理领域十分实用且重要的方法。
Spectrum Engine 分析; private: bool initialize(); bool selectFormat(); void stopRecording(); void stopPlayback(); void setState(QAudio::State state); void setState(QAudio::Mode mode, QAudio::State state); void setFormat(const QAudioFormat &format); void setRecordPosition(qint64 position, bool forceEmit = false); void setPlayPosition(qint64 position, bool forceEmit = false); void calculateLevel(qint64 position, qint64 length); void calculateSpectrum(qint64 position); void setLevel(qreal rmsLevel, qreal peakLevel, int numSamples); private: QAudio::Mode m_mode; QAudio::State m_state; bool m_generateTone; SweptTone m_tone; /* WavFile */ QFile* m_file; WavFile m_wavFile; QAudioFormat m_format; /*audioInput*/ const QList<QAudioDeviceInfo> m_availableAudioInputDevices; QAudioDeviceInfo m_audioInputDevice; QAudioInput* m_audioInput; QIODevice* m_audioInputIODevice; qint64 m_recordPosition; /*audioOutput*/ const QList<QAudioDeviceInfo> m_availableAudioOutputDevices; QAudioDeviceInfo m_audioOutputDevice; QAudioOutput* m_audioOutput; qint64 m_playPosition; QBuffer m_audioOutputIODevice;
/*ByteArray*/ QByteArray m_buffer; qint64 m_dataLength; qreal m_rmsLevel; qreal m_peakLevel; int m_spectrumLengthBytes; QByteArray m_spectrumBuffer; SpectrumAnalyser m_spectrumAnalyser; qint64 m_spectrumPosition; int m_count; public slots: void startRecording(); void startPlayback(); void suspend(); void setAudioInputDevice(const QAudioDeviceInfo &device); void setAudioOutputDevice(const QAudioDeviceInfo &device); private slots: void audioNotify(); void audioStateChanged(QAudio::State state); void audioDataReady(); void spectrumChanged(const FrequencySpectrum &spectrum); signals: void stateChanged(QAudio::Mode mode, QAudio::State state); void infoMessage(const QString &message, int durationMs); void errorMessage(const QString &heading, const QString &detail); |
void formatChanged(const QAudioFormat &format);
void bufferDurationChanged(qint64 duration);
void dataDurationChanged(qint64 duration);
void recordPositionChanged(qint64 position);
void playPositionChanged(qint64 position);
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum);
spectrumanalyser 分析
class SpectrumAnalyser : public QObject
public:
void setWindowFunction(WindowFunction type);
void calculate(const QByteArray &buffer, const QAudioFormat &format);
bool isReady() const;
void cancelCalculation();
signals:
void spectrumChanged(const FrequencySpectrum &spectrum);
private slots:
void calculationComplete(const FrequencySpectrum &spectrum);
private:
void calculateWindow();
private:
SpectrumAnalyserThread* m_thread;
enum State {
Idle,
Busy,
Cancelled
};
State m_state;
2. class SpectrumAnalyserThread : public QObject
public slots:
void setWindowFunction(WindowFunction type);
void calculateSpectrum(const QByteArray &buffer,int inputFrequency,int bytesPerSample);
signals:
void calculationComplete(const FrequencySpectrum &spectrum);
private:
void calculateWindow();
private:
#ifndef DISABLE_FFT
FFTRealWrapper* m_fft;
#endif
const int m_numSamples;
WindowFunction m_windowFunction;
#ifdef DISABLE_FFT
typedef qreal DataType;
#else
typedef FFTRealFixLenParam::DataType DataType;
#endif
QVector<DataType> m_window;
QVector<DataType> m_input;
QVector<DataType> m_output;
FrequencySpectrum m_spectrum;
QThread* m_thread;
};
FFT
QMetaObject
FFTReal
http://www.sand-tower.net/archives/98
http://blog.csdn.net/hztj2005/article/details/7538698
开源软件Audacity架构(2)
TrackPanel
在Audacity中最主要的界面是TrackPanel,是用来显示波形图的。这是一个由Audacity绘制的客户控件。TrackPanel是由如小一点的面板这样的组件组成的,这些面板会显示音轨信息、时间线的标尺、波幅的标尺、要显示波形图的音轨、波谱或文本标签。可以拖动来移动这些音轨和改变它们的大小。音轨包含的文本标签是使用的我们自己重新实现的可编辑的文本框,而不是使用的内置的文本框。你可能认为这些标尺和面板每个都是wxWidget组件,但是不是。
阅读Audacity的代码的时候,应该意识到只有一部分的代码是必不可少的。这些库提供了很多可选的功能 — 当然,使用这些功能的用户可能不会认为这些功能是可选的。例如,除了Audacity内置的声音效果之外,Audacity还支持LADSPA(Linux Audio Developer’s Simple Plugin API)来支持可动态加载的音频效果插件。Audacity的VAMP API也做了同样的事情来支持音频分析的插件。没有这些API,Audacity的功能就没有这么丰富,但是这并不表明Audacity就完全依赖这些功能。
http://zh.wikipedia.org/wiki/离散时间傅里叶变换
http://www.fftw.org/benchfft/ffts.html
2012.7.20
progressbar 只是管进度显示,the left_top form
const qreal play = qreal(m_playPosition) / m_bufferDuration;
bar.setLeft(rect().left() + play * rect().width());
const qreal record = qreal(m_recordPosition) / m_bufferDuration;
bar.setRight(rect().left() + record * rect().width());
//painter.fillRect(bar, bufferColor); //the right color rect
QRect window = rect();
const qreal windowLeft = qreal(m_windowPosition) / m_bufferDuration;
window.setLeft(rect().left() + windowLeft * rect().width());
const qreal windowWidth = qreal(m_windowLength) / m_bufferDuration;
window.setWidth(windowWidth * rect().width());
//painter.fillRect(window, windowColor); //bar record rect
spectrograph 显示整体内容的部分 the_Left_button form
LevelMeter 显示the_right_side
settingsdialog 设置声音信息 the settingdialog
tonegeneratordialog 设置波形相关的内容信息,
toneGeneratorLayout->addWidget(m_amplitudeSlider, 2, 1); //the import slider to the spectrum
tonegenerator =====> 关系到波长波动的大小,是一个记算类比较重要
generateTone(const SweptTone &tone, const QAudioFormat &format, QByteArray &buffer)
phase += phaseStep;
utils 也是对数据做处理分析。
qint64
mainwidget
killTimer(m_infoMessageTimerId);
connect(m_loadFileAction, SIGNAL(triggered(bool)), this, SLOT(showFileDialog()));
connect(m_generateToneAction, SIGNAL(triggered(bool)), this, SLOT(showToneGeneratorDialog()));
connect(m_recordAction, SIGNAL(triggered(bool)), this, SLOT(initializeRecord()));
Engine::calculateLevel pos 38268 len 1600 rms 0.530365 peak 0.749939
Engine::calculateSpectrum QThread(0x1016016d0) count 0 pos 38268 len 8192 spectrumAnalyser.isReady true
SpectrumAnalyser::calculate QThread(0x1016016d0) state 0
Engine::spectrumChanged pos 38268
mainwidget 分析:
void MainWidget::reset()
{
#ifndef DISABLE_WAVEFORM
m_waveform->reset();
#endif
m_engine->reset();
m_levelMeter->reset();
m_spectrograph->reset();
m_progressBar->reset();
}
m_engine->generateTone(tone);
setMode(GenerateToneMode);
const qreal amplitude = m_toneGeneratorDialog->amplitude();
if (m_toneGeneratorDialog->isFrequencySweepEnabled()) {
m_engine->generateSweptTone(amplitude);
} else {
const qreal frequency = m_toneGeneratorDialog->frequency();
const Tone tone(frequency, amplitude);
m_engine->generateTone(tone);
updateButtonStates();
}
reset();
setMode(RecordMode);
if (m_engine->initializeRecord())
updateButtonStates();
和waveform 相关的内容:
1。m_waveform(new Waveform(m_engine->buffer(), this))
2。m_waveform->initialize(format, WaveformTileLength, WaveformWindowDuration);
--->MainWidget::formatChanged(const QAudioFormat &format)
___>CHECKED_CONNECT(m_engine, SIGNAL(formatChanged(const QAudioFormat &)),
this, SLOT(formatChanged(const QAudioFormat &)));
3。 m_waveform->positionChanged(positionBytes);
--->void MainWidget::positionChanged(qint64 positionUs)
___>m_engine,,,m_progressBar,
4。m_waveform->dataLengthChanged(dataLength);
--->void MainWidget::dataDurationChanged(qint64 duration)
5。m_progressBar->setMinimumHeight(m_waveform->minimumHeight());
6。m_waveform->setLayout(waveformLayout.data());
7。windowLayout->addWidget(m_waveform);
--->void MainWidget::createUi()
8。m_waveform->reset();
--->void MainWidget::reset()
const QByteArray &buffer
m_buffer(buffer)
, m_dataLength(0)
, m_position(0)
, m_active(false)
, m_tileLength(0)
, m_tileArrayStart(0)
, m_windowPosition(0)
, m_windowLength(0)
private:
const QByteArray& m_buffer;
qint64 m_dataLength; //[2]
qint64 m_position;
QAudioFormat m_format; // [2] the Format audio
bool m_active;
QSize m_pixmapSize;
QVector<QPixmap*> m_pixmaps; //[?]
struct Tile {
// Pointer into parent m_pixmaps array
QPixmap* pixmap;
// Flag indicating whether this tile has been painted
bool painted;
};
QVector<Tile> m_tiles; //[?]
// Length of audio data in bytes depicted by each tile
qint64 m_tileLength;
// Position in bytes of the first tile, relative to m_buffer
qint64 m_tileArrayStart;
qint64 m_windowPosition;
qint64 m_windowLength;
int tim;
50 m_waveform->mininumHight m_engine->[5]
QHBoxLayout(0x10154c060) waveformLayout() m_engine->[6]
1024 dataLength m_engine[4]
1480 positionBytes m_engine->[3]
Waveform 分析:
WAVEFORM_DEBUG << "Waveform::paintEvent" << "windowPosition" << m_windowPosition
<< "windowLength" << m_windowLength;
WAVEFORM_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight;
int destLeft = 0;
int destRight = 0;
painter.drawPixmap(destRect, *tile.pixmap, sourceRect);
createPixmaps(event->size());
2012.7.23
Wavfile 分析
QAudioFormat m_format;
qint64 m_dataLength;
m_format.setSampleType(QAudioFormat::SignedInt);
m_format.setByteOrder(QAudioFormat::BigEndian);
m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
m_format.setCodec("audio/pcm");
m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
m_dataLength = device.size() - HeaderLength;
if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
|| memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
&& memcmp(&header.riff.type, "WAVE", 4) == 0
&& memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
&& header.wave.audioFormat == 1 // PCM
) {
if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
m_format.setByteOrder(QAudioFormat::LittleEndian);
else
m_format.setByteOrder(QAudioFormat::BigEndian);
testformat
codec /audio/pcm
Frequency(Hz) 22050
channels 1
SampleType Signedint
sample size(bits) 8
Endianess LittleEndian
Qt 音频播放
使用QAudioOutput播放音频,播放出来的声音一直是沙沙的声音!!!
请问各位有没有遇到过这个问题 怎么解决的
C/C++ code
inputFile.setFileName("d:/001.mp3");
inputFile.open(QIODevice::ReadOnly);
QAudioFormat format;
format.setFrequency(8000);
format.setChannels(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
return;
}
audio = new QAudioOutput(format, this);
audio->start(&inputFile);
bool Engine::initialize()
const qint64 bufferLength = audioLength(m_format, BufferDurationUs);
m_buffer.resize(bufferLength);
m_buffer.resize(bufferLength);
m_buffer.fill(0);
::generateTone(m_tone, m_format, m_buffer);
m_dataLength = m_buffer.size();
const qint64 length = m_wavFile.readData(*m_file, m_buffer, m_format);
if (selectFormat()) {
const qint64 bufferLength = audioLength(m_format, BufferDurationUs);
m_buffer.resize(bufferLength);
m_buffer.fill(0);
emit bufferDurationChanged(BufferDurationUs);
if (m_generateTone) {
if (0 == m_tone.endFreq) {
const qreal nyquist = nyquistFrequency(m_format);
m_tone.endFreq = qMin(qreal(SpectrumHighFreq), nyquist);
}
// Call function defined in utils.h, at global scope
::generateTone(m_tone, m_format, m_buffer);
m_dataLength = m_buffer.size();
emit dataDurationChanged(bufferDuration());
setRecordPosition(bufferDuration());
result = true;
} else if (m_file) {
const qint64 length = m_wavFile.readData(*m_file, m_buffer, m_format); //import for read file data
if (length) {
m_dataLength = length;
emit dataDurationChanged(dataDuration());
setRecordPosition(dataDuration());
result = true;
}
} else {
m_audioInput = new QAudioInput(m_audioInputDevice, m_format, this);
m_audioInput->setNotifyInterval(NotifyIntervalMs);
result = true;
}
m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this);
m_audioOutput->setNotifyInterval(NotifyIntervalMs);
m_spectrumLengthBytes = SpectrumLengthSamples *
(m_format.sampleSize() / 8) * m_format.channels();
AudioOutput
case QAudio::AudioOutput:
length = m_audioOutput->bufferSize();
if (m_audioOutput) {
if (QAudio::AudioOutput == m_mode &&
QAudio::SuspendedState == m_state) {
#ifdef Q_OS_WIN
// The Windows backend seems to internally go back into ActiveState
// while still returning SuspendedState, so to ensure that it doesn't
// ignore the resume() call, we first re-suspend
m_audioOutput->suspend();
#endif
m_audioOutput->resume();
} else {
m_mode = QAudio::AudioOutput;
CHECKED_CONNECT(m_audioOutput, SIGNAL(stateChanged(QAudio::State)),
this, SLOT(audioStateChanged(QAudio::State)));
CHECKED_CONNECT(m_audioOutput, SIGNAL(notify()),
this, SLOT(audioNotify()));
C/C++ code
file.setFileName("/home/test0.raw");
format.setFrequency(8000);
format.setChannels(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(format))
{
qWarning()<<"default format not supported try to use nearest";
format = info.nearestFormat(format);
}
audioOut = new QAudioOutput(format,this);
connect(PlayBtn,SIGNAL(clicked()),this,SLOT(playing()));
connect(StopBtn,SIGNAL(clicked()),this,SLOT(stop()));
}
void play::playing()
{
file.open(QIODevice::ReadOnly);
QMessageBox::information(this,tr("ok"),tr("open this file successfully!"));
audioOut->start(&file);
}
void play::stop()
{
audioOut->stop();
file.close();
exit(0);
}
http://www.developer.nokia.com/Community/Wiki/使用Qt_Multimedia_API_进行录音和播音
%!xxd
:%!xxd -r
dd if=/dev/fd0 of=disk.img bs=1440k
/*
* by microsky2813@hotmail.com
*
*/
#include<QApplication>
#include<phonon/videoplayer.h>
#include<phonon/mediasource.h>
#include<phonon/VideoWidget>
#include<phonon>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Phonon::MediaObject *media = new Phonon::MediaObject();
Phonon::VideoWidget * vw=new Phonon::VideoWidget();//视频
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput();//声音
media->setCurrentSource(Phonon::MediaSource("10.wmv"));
Phonon::createPath(media, audioOutput);
Phonon::createPath(media,vw);
Phonon::VolumeSlider *volumeSlider = new Phonon::VolumeSlider(vw);
volumeSlider->setAudioOutput(audioOutput);
media->play();
vw->show();
return app.exec();
}
http://blog.csdn.net/microsky2813/article/details/5279856
length = m_audioOutput->bufferSize();
m_audioOutput->suspend();
const qint64 playPosition =
qMin(dataDuration(), m_audioOutput->processedUSecs());
setPlayPosition(playPosition);
通常使用三个参数来表示声音,量化位数,取样频率和声道数。声道有单声道和立体声之分,取样频率一般有11025Hz(11kHz) ,22050Hz(22kHz)和44100Hz(44kHz) 三种,不过尽管音质出色,但在压缩后的文件体积过大!相对其他音频格式而言是一个缺点,其文件大小的计算方式为:
Wav File
av File
WAV格式文件所占容量(KB) = (取样频率 X 量化位数 X 声道) X 时间 / 8 (字节= 8bit) 每一分钟WAV格式的音频文件的大小为10MB,其大小不随音量大小及清晰度的变化而变化。
目前支持WAV设计的手机主要为智能手机,如索尼爱立信P910和诺基亚N90以及采用微软OS的多普达等手机,而其它一些非智能手机的产品,如果宣传支持WAV格式则多半属于只是支持单声道
m_buffer=(1411 *16*2) *100 /8
http://netghost.narod.ru/gff/graphics/summary/micriff.htm
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
你读文件头时读出WAVEFORMATEX,该结构的nAvgBytesPerSec表示每秒平均的字节数,
也可以这么计算nAvgBytesPerSec = nChannels * nSamplesPerSec * wBitsPerSample / 8;
在这个结构后面紧跟 "data "(就是6461 7461),在后面先是数据大小,然后是具体数据.
用数据大小除以nAvgBytesPerSec.
176400
1411 200
45158400
下面是WAV格式头的描述:
名称 字节 描述
ckID 4 ASCII字符串“fmt ”。注意串中最后一个字符为空格,
所有的块的ID必须是4字符,这样最后的空格用于补充
小于4字符的串。
nChunkSize 4 这是一个32位的无符号整型值,它保存的是以字节计的
整个“fmt ”块的长度。注意WAV文件中所有多字节整
型值都是低字节在前的方式表示的。例如,如果一个
WAV文件的块尺寸为16,它在文件中的16进制表示为:
10 00 00 00。
wFormatTag 2 它定义了WAV文件中的音频数据是怎样编码的。此值常为
1,表示Pulse Code Modulation(PCM)。其它值常常为
压缩方式编码,需要更复杂的算法。
nChannels 2 这是WAV文件中音频表现的通道数。单声道声音只有1个
通道;立体声有两个通道。多于2个通道是可能的(例
如环绕声),但很少见。
nSamplesPerSec 4 采样速率用每秒的采样数或Hz表示。此值的倒数两个采
样间的以秒计的时间值。典型值为11025(电话质量),
22050(FM质量),44100(CD质量)。几乎没有小于
8000Hz大于48000Hz的采样速率。
nAvgBytesPerSec 4 播放程序实时处理播放音频数据平均每秒字节数。对于
PCM音频这是多余的,因为你可以通过采样速率、通道
数、每个采样的字节数相乘得到。
nBlockAlign 2 这个数字告诉你一次输出的字节数。在PCM中,此值等于
每次采样的字节数乘以通道数。
nBitsPerSample 2 此值仅在PCM录音中出现。它定义了每次采样的音频幅度
的位数。通常为8或16。8位音频文件仅有256级不同的
幅度,因此质量较低且有附带的被称为量化失真的嘶音。
16位的音频文件的声音质量较好但是尺寸是前者的两倍
(假定采样速率和通道数相同)。
包含了声音的质量, 即采样频率, 如44100Hz啦, 而每次取样的位数也是在这个头部
里记录, 例如16位(2字节), 然后是单声道还是双声道
例如CD音质的wav, 它一秒钟的长度就是44100*2(16位)*2(双声道)=176400字节
你只要理解它的存储结构, 可以计算出精确的时间. Wav文件的头部数据结构在很多
有关wav的构件代码中都有定义.
02:10:00
0319 0750
timeLcd->display("00:00");
- QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
timeLcd->display(displayTime.toString("mm:ss"));
position==== 199494240 the int num /1000000 199
datalength 76585070
"00:03:19.693"
"00:01:16.661"
audioNotify() has been call
position==== 199598730 the int num /1000000 199
datalength 76585070
"00:03:19.797"
"00:01:16.661"
audioNotify() has been call
position==== 199691609 the int num /1000000 199
datalength 76585070
"00:03:19.890"
"00:01:16.661"
audioNotify() has been call
position==== 199796099 the int num /1000000 199
datalength 76585070
"00:03:19.995"
"00:01:16.661"
audioNotify() has been call
position==== 199900589 the int num /1000000 199
datalength 76585070
"00:03:19.100"
"00:01:16.661"
audioNotify() has been call
position==== 199993469 the int num /1000000 199
datalength 76585070
"00:03:19.193"
"00:01:16.661"
audioStateChanged() has been call Engine::audioStateChanged from m_state to 3
0
-24
-60
1.0
0.5
0.0
-0.5
-1.0
http://www.avrvi.com/labview_start/Waveform_Display_Control%20.html
幅值/时间
我们可以清楚地看到这两种显示工具的区别,它们地实现方法和过程不同,在程序框图也可以看出,波形图表产生在循环体内,这样每得到一个数据点,就立刻显示一个;而波形图产生在循环体外,100个数据都产生之后,跳出循环,然后一次显示出整个数据曲线。程序运行第二次时,波形图表的X轴刻度就会随之增加,由0~99变为100~199,表示数据点的增加;而波形图的X轴刻度并没有发生变化,还是0~99,表示只显示当前的数据。
假设其数据点数,幅值和频率都相同
幅度 - 时间」图(波形)和「频率 - 时间」图(频谱)来表示
http://www.cnblogs.com/conmajia/default.html?page=2
快速傅里叶变换
快速傅里叶变换是将信号(在这里,就是音频信号)变换到其频域的一种操作。
之后,可以看到输入信号的频率组成方式。快速傅里叶变换(FFT)是一种高效计算傅里叶变换的算法。
逆操作(IFFT,逆傅里叶变换)从频域获取数据,输出时域值。我们可以利用该算法将图形画到音频中
我们可以用 Cooledit 之类的程序来查看结果
Garrett Hoofman 的 Wave File Library。该库用于产生 wav 输出文件
·任意 IFFT 算法库
为了在我们自己的程序中实现这种效果,就需要研究、分析它们的原理,掌握其规律,然后加以实现。
很明显,从软件可重用性以及各种随之而来的好处考虑,我们要求将这个“波形显示”效果做成一个控件(Control)
凡是二者共同点,加以重点实现;凡二者不同之处,通过设置属性(Property)进行更改。最后绘制时,基于所设置的属性,使用共同方法加以实现。
对于此自定义控件,需要每次更新时在其 OnPaint() 事件中对整个控件进行绘制。绘制顺序为:背景 - 网格 - 波形,如此保证所有部分均正确画出且无遮挡。
因此可以确定这个数组是和控件绘图画布宽度一致的
绘图最重要的是算法部分,如何计算如网格位置,如何将图形整体平移,如何设置波形值是本控件的重点和难点部分。
http://www.cnblogs.com/conmajia/archive/2012/05/10/develop-goodlooking-controls-series-1.html 鼠标改变大小的运用
在Paint里画出一条经过所有节点的曲线DrawCurve
随便画个十字准星表示当前节点
鼠标按下,判断是否在某个已有节点里,如果有,标记之,否则添加新节点
刷新画图
原来耳膜受声音影响而振动时振动幅度不是与声音强度成比例,而是与声音强度的对数成正比关系。于是,人们便用声音强度的值取其以10为底的对数值“1”作为声强单位,单位名字叫“贝尔”,每“贝尔”的十分之一叫“分贝”,用“db”表示。
- MyWidget::MyWidget(...) : QWidget(...) {
- ... setAcceptDrops(TRUE); //接收被放下的媒体
- }//当一个拖动正在进行并且鼠标进入这个窗口部件,这个事件处理函数被调用
- void MyWidget::dragEnterEvent(QDragEnterEvent* event) {
- event->accept( QTextDrag::canDecode(event) || QImageDrag::canDecode(event) );
- }//当拖动在这个窗口部件上被放下,这个事件处理器被调用
- void MyWidget::dropEvent(QDropEvent* event) {
- QImage image;
- QString text;
- if ( QImageDrag::decode(event, image) ) {//解码图片
- insertImageAt(image, event->pos()); //在窗口部件中插入图片
- } else if ( QTextDrag::decode(event, text) ) {
- insertTextAt(text, event->pos());
- }
- }
http://doc.trolltech.com/4.6/stylesheet-examples.html#customizing-qslider
你可以把slider和一个progress进度条connect一下,应该可以满足你的需求
http://www.qtforum.org/index.php?form=Search&searchID=399350&highlight=area+zoom
http://www.kuqin.com/qtdocument/qscrollview.html#details
http://topic.csdn.net/u/20120229/10/bb92334c-de85-48e4-b548-2df5f48ad47f.html
http://topic.csdn.net/u/20120229/10/bb92334c-de85-48e4-b548-2df5f48ad47f.html
音频播放的音调、级别和速度等
https://www.deleak.com/blog/category/音频处理/
上边操作中,把波 invert,使之和原始波相位相差180度(所以播放时候无声)。而后一步又删除了两个采样点,所以相位相差小于180读,相对较低和较高的频率都被抵消,剩下对人耳比较敏感的人声。
同样的,主动式降噪耳机,阵列式 mic ,都是同样道理,利用拾音mic 拾取环境噪声,然后计算出反向声波消除音频中的噪声。
http://zh.wikipedia.org/wiki/叠加原理
可以看出,频率越高,减少的越严重,11k 以后基本为零。对人耳相对敏感的高音区域缺少,这就是造成“闷闷的感觉”主要原因。
调整乐器类音频,要熟悉乐器的属性和特性,这样才能达到最佳效果。因为每种乐器发声频率都是不同的,所以需要查找其频率并进行针对性调节。首先阅读文档:常见乐器的频率特性 可知,钢琴 25~50 Hz为低音共振频率,64~125 Hz为常用的低音区,2~5 kHz影响临场感。
所以我们载入音乐文件后,全选声轨,点击菜单 effect –equalization 调节eq:
具体问题具体分析,因为要让它听起来更清晰,所以把高音部分增强,低音部分减弱。重复两次,试听效果比较不错,高音部分已经比较清晰可是低音部分损失了。
点击菜单 file-import,重新载入相同文件,可以看到两个文件,四条声轨并列展示在软件中。全选刚刚载入的声轨,点击菜单 effect –equalization 调节eq:
Noise reduction(dB) 24 降噪技术 | 降噪 | 噪声降低 | 视频降噪
sensitivity(dB) 0.00 灵敏度 | 敏感性 | 敏感度 | 敏感
Frequency smoothing(Hz) 660 频域平滑
Attack/decay time(sec) 0.74 粹发音及衰减
https://www.deleak.com/blog/category/音频处理/
分贝
分贝的计算很简单,对于振幅类物理量,如电压、电流强度等,将测量值与
基准值相比后求常用对数再乘以20;对于它们的平方项的物理量如功率,取
对数后乘以10就行了;不管是振幅类还是平方项,变成分贝后它们的量级是
一致的,可以直接进行比较、计算。
分贝(dB)的英文为decibel,它的词冠来源于拉丁文decimus,意思是十分之
一,decibel就是十分之一贝尔。分贝一词于1924年首先被应用到电话工程
中。
从声压--电压--AD变换后的数值校准后就能从采集得的数据反算出声压和声压级。
dB=20 * Log10(X) 但是其中的X是如何取到的不是很清楚.麻烦详细说明一下
一般都把1表示为0分贝,即是按公式dB=20 * Log10(X)计算。X=abs(fft(x)),x是信号
你的意思我明白了,那就是我采集到的只是信号的数据然后进行FFT运算,取绝对值后再进行dB运算,是这样吗? 还有我试了一下,我把一组数据(是个数组长度个数为256个.)进行FFT运算后看数据没有任何变化呀? FFT是作什么用的?我只有现在的算法,但是不知道是作什么的,怎么作的. FFT运算完成后计算出的数据很大.................我现手头有一个软件他算出来的是-30多......dB有负值吗? |
原帖由 sleept 于 2009-3-31 09:34 发表 我是这样计算的,采集到256个数据后进行FFT变换. 变换完成后还是256个数据.循环计算每一个数据的绝对值dB,也就是 arry(256) FFT(arry) for i=0 to 255 tempdb=tempdb + 20 * Log10( abs(arry(i))) next tempdb = tempdb / 256 然后tempdb就是这256个数据的平均分贝,不知道这样作对不对? 不明白楼主在笫5层说的“我把一组数据(是个数组长度个数为256个.)进行FFT运算后看数据没有任何变化呀”,难道FFT后和FFT之前是一样的? 一般在FFT之前是时域数据,FFT之后是频域数据,而且在频域数据中一般只有一半是有效的。上表达的关系不下分明白,在FFT之后把谱线值相加,不知求什么?又分贝值不能这样相加: tempdb=tempdb + 20 * Log10( abs(arry(i))) 同时dB值会有负值,上一帖子中说到,以1为参考值,代表0dB,小于1的值便是负值。 |
我采集到的数据是可以保存成WAV文件的对吧?只不过是少了WAV文件头信息部份.我可以用API补齐这部份. 假如说现在有这么一个文件,他是16K采样率,16Bit量化率,每秒数据流量是32000那,区块对齐数就是2. 也就是说以每两个字节为一个区块,每一个区块最大是32768,最少为-32768 而0是静音. 那我就一下先取256个区块进行FFT计算. 我这里有一个FFT算法. |
1.用麦克风采集校准信号(dB 信号),获得电压值-压强(放大仪器的灵敏度),此信号作为基准,采用fft得到基准幅值 vs 频率 2.采集实验信号,得到的压强,fft变换,与基准幅值作比,得到实验信号的dB |
X=1000000000000000 (多少个了?)
10lgX=150dB
X=0.000000000000001
10lgX=-150 dB
DB在缺省情况下总是定义功率单位,以 10lg 为计。当然某些情况下可以用信号强度(Amplitude)来描述功和功率,这时候就用 20lg 为计。不管是控制领域还是信号处理领域都是这样。比如有时候大家可以看到 dBmV 的表达。
在dB,dBm计算中,要注意基本概念。比如前面说的 0dBw = 10lg1W = 10lg1000mw = 30dBm;又比如,用一个dBm 减另外一个dBm时,得到的结果是dB。如:30dBm - 0dBm = 30dB
一般来讲,在工程中,dB和dB之间只有加减,没有乘除。而用得最多的是减法:dBm 减 dBm 实际上是两个功率相除,信号功率和噪声功率相除就是信噪比(SNR)。dBm 加 dBm 实际上是两个功率相乘,这个已经不多见(我只知道在功率谱卷积计算中有这样的应用)。dBm 乘 dBm 是什么,1mW 的 1mW 次方?除了同学们老给我写这样几乎可以和歌德巴赫猜想并驾齐驱的表达式外,我活了这么多年也没见过哪个工程领域玩这个。
dB是功率增益的单位,表示一个相对值。当计算A的功率相比于B大或小多少个dB时,可按公式10 lg A/B计算。例如:A功率比B功率大一倍,那么10 lg A/B = 10 lg 2 = 3dB。也就是说,A的功率比B的功率大3dB;如果A的功率为46dBm,B的功率为40dBm,则可以说,A比B大6dB;如果A天线为12dBd,B天线为14dBd,可以说A比B小2dB。
dBm是一个表示功率绝对值的单位,计算公式为:10lg功率值/1mW。例如:如果发射功率为1mW,按dBm单位进行折算后的值应为:10 lg 1mW/1mW = 0dBm;对于40W的功率,则10 lg(40W/1mW)=46dBm。
声音的响度。声音其实是经媒介传递的快速压力变化。当声音於空气中传递,大气压力会循环变化。每一秒内压力变化的次数叫作频率,量度单位是赫兹(Hz),其定义为每秒的周期数目。
分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度声音强度,常用dB表示。“分”(deci-)指十分之一,个位是“贝”(bel),但一般只采用分贝。
声音其实是经媒介传递的快速压力变化。当声音於空气中传递,大气压力会循环变化。每一秒内压力变化的次数叫作频率,量度单位是赫兹(Hz),其定义为每秒的周期数目。 频率越高,声音的音调越高。
http://www.animations.physics.unsw.edu.au/jw/dB.htm
- So if you read of a sound pressure level of 86 dB, it means that
20 log (p2/p1) = 86 dB
where p1 is the sound pressure of the reference level, and p2 that of the sound in question. Divide both sides by 20: log (p2/p1) = 4.3
p2/p1 = 104.3
http://www.qiliang.net/old/qt/tutorial2-06.html
http://www.qiliang.net/old/qt/canvas.html
http://www.cnblogs.com/xmphoenix/archive/2011/01/18/1938567.html
2012.8.6
如果项目比较多的话用QGraphicsView 架构吧,C++ GUI QT4 第二版有类似的列子!是那个画底图程序的例子!
Qpainter的成员函数好好看看,关于坐标变换,有现成的
http://topic.csdn.net/u/20101129/09/74d965dc-55f5-401b-8187-7eaa0af4de3f.html
http://blog.chinaunix.net/attachment/attach/24/21/97/0124219701cf5f4c58dcef6eb69ce241b8837bef90.pdf
http://www.cnblogs.com/xmphoenix/category/278940.html
http://www.qtcentre.org/blog.php
http://www.blitzbasic.com/Community/posts.php?topic=84391
http://www.kuqin.com/qtdocument/qpainter.html#details
MAC 下用Qt 。。。。
qmake -spec macx-g++ qwt.pro
2012。8。10
出来了。因该是:
QCursor a ;
QPixmap pixmap(“加载你画的图片”) ;
a = QCursor(pixmap,-1,-1);
setCursor(a) ;
QPixmap pixmap(“加载你画的图片”) ;
setCursor(&pixmap) ;
http://fossies.org/unix/privat/audacity-minsrc-2.0.1.tar.gz/index_o.html
带源分析。。
http://fossies.org/dox/audacity-minsrc-2.0.1/src_2Envelope_8h_source.html#l00088
http://www.scs.ryerson.ca/~lkolasa/CppWavelets.html
scale 是根据什么实现的。。。 放大,缩小是不是也得重新画。
打开Terminal,输入如下命令:
cd /usr/share/vim
sudo vim vimrc
两行命令之后,会出现VIM,在set backspace=2这行下插入(VIM的操作不赘述,想做这个修改的肯定都会使VIM)如下配置
set ai " auto indenting
set history=100 " keep 100 lines of history
set ruler " show the cursor position
syntax on " syntax highlighting
set hlsearch " highlight the last searched term
filetype plugin on " use the file type plugins
" When editing a file, always jump to the last cursor position
autocmd BufReadPost *
if ! exists("g:leave_my_cursor_position_alone") |
if line("'"") > 0 && line ("'"") <= line("$") |
exe "normal g'"" |
endif |
endif
最后
以上就是风趣宝马为你收集整理的demoddd的全部内容,希望文章能够帮你解决demoddd所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复