demoddd

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> 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


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表示为下面的求和形式:

292efb98b85baf95bab720622f2a08d6.png

其中8399b1e7c5548479381ab8762ab9250e.png是傅里叶振幅。直接使用这个公式计算的计算复杂度04a727b4c56b63e9130a2e8a42eb9038.png,而快速傅里叶变换FFT)可以将复杂度改进为c3e4fa8eaf0b206fd83d620e2e0211a1.png。计算复杂度的降低以及数字电路计算能力的发展使得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                           m_window;

    QVector                           m_input;

    QVector                           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还支持LADSPALinux Audio Developer’s Simple Plugin API)来支持可动态加载的音频效果插件。AudacityVAMP API也做了同样的事情来支持音频分析的插件。没有这些APIAudacity的功能就没有这么丰富,但是这并不表明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 相关的内容: 


1m_waveform(new Waveform(m_engine->buffer(), this))


2m_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,


4m_waveform->dataLengthChanged(dataLength);

--->void MainWidget::dataDurationChanged(qint64 duration)



5m_progressBar->setMinimumHeight(m_waveform->minimumHeight());


6m_waveform->setLayout(waveformLayout.data());


7windowLayout->addWidget(m_waveform);

--->void MainWidget::createUi()



8m_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           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(header.wave.numChannels));

 m_format.setCodec("audio/pcm");

 m_format.setFrequency(qFromLittleEndian(header.wave.sampleRate));

 m_format.setSampleSize(qFromLittleEndian(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 [email protected]
*
*/
#include
#include
#include
#include
#include


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) 三种,不过尽管音质出色,但在压缩后的文件体积过大!相对其他音频格式而言是一个缺点,其文件大小的计算方式为:

  

3812b31bb051f8191e954534dab44aed2e73e718.jpg.png

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轴刻度就会随之增加,由099变为100199,表示数据点的增加;而波形图的X轴刻度并没有发生变化,还是099,表示只显示当前的数据。


假设其数据点数,幅值和频率都相同



幅度 - 时间」图(波形)和「频率 - 时间」图(频谱)来表示



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”表示。


  1. MyWidget::MyWidget(...) :    QWidget(...)  {  
  2.      ...     setAcceptDrops(TRUE); //接收被放下的媒体  
  3.   }//当一个拖动正在进行并且鼠标进入这个窗口部件,这个事件处理函数被调用    
  4. void MyWidget::dragEnterEvent(QDragEnterEvent* event)  {   
  5.     event->accept( QTextDrag::canDecode(event) ||         QImageDrag::canDecode(event)  );  
  6.   }//当拖动在这个窗口部件上被放下,这个事件处理器被调用  
  7.   void MyWidget::dropEvent(QDropEvent* event)  {   
  8.     QImage image;  
  9.      QString text;   
  10.      if ( QImageDrag::decode(event, image) ) {//解码图片  
  11.       insertImageAt(image, event->pos()); //在窗口部件中插入图片  
  12.      } else if ( QTextDrag::decode(event, text) ) {   
  13.      insertTextAt(text, event->pos());  
  14.       }  
  15.   } 



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 以后基本为零。对人耳相对敏感的高音区域缺少,这就是造成闷闷的感觉主要原因。


调整乐器类音频,要熟悉乐器的属性和特性,这样才能达到最佳效果。因为每种乐器发声频率都是不同的,所以需要查找其频率并进行针对性调节。首先阅读文档:常见乐器的频率特性 可知,钢琴 2550 Hz为低音共振频率,64125 Hz为常用的低音区,25 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 发表 back.gif

我是这样计算的,采集到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 的表达。

dBdBm计算中,要注意基本概念。比如前面说的 0dBw = 10lg1W = 10lg1000mw = 30dBm;又比如,用一个dBm 减另外一个dBm时,得到的结果是dB。如:30dBm - 0dBm = 30dB


一般来讲,在工程中,dBdB之间只有加减,没有乘除。而用得最多的是减法: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的功率为46dBmB的功率为40dBm,则可以说,AB6dB;如果A天线12dBdB天线为14dBd,可以说AB2dB 



  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

你可能感兴趣的:(知识要点)