feedbackhandler.cpp

来自「一个非常好用的MP3音乐播放控件」· C++ 代码 · 共 750 行 · 第 1/2 页

CPP
750
字号
/*****************************************************************
|
|      Xaudio SDK. Sample Feedback Handler for Windows
|
|
|      (c) 1996-1999 Xaudio, Inc
|      Author: Gilles Boccon-Gibod (gilles@mpegtv.com)
|
 ****************************************************************/

/*----------------------------------------------------------------------
|       includes
+---------------------------------------------------------------------*/
#include "feedback.h"
#include "fft.h"

#include <windows.h>

/*----------------------------------------------------------------------
|       constants
+---------------------------------------------------------------------*/
#define FEEDBACK_MODULE_VERSION     "1.0"
#define FEEDBACK_NB_BANDS           64
#define FEEDBACK_DISPLAY_WIDTH      224
#define FEEDBACK_DISPLAY_HEIGHT     68

/*----------------------------------------------------------------------
|       types and classes
+---------------------------------------------------------------------*/
class PaintBox {
public:
       	 PaintBox(HDC dc, unsigned int width, unsigned int height);
	    ~PaintBox();
        void ClearPixels();
        inline void SetPixel(unsigned int x, unsigned int y, DWORD color) {
            if (x >= FEEDBACK_DISPLAY_WIDTH ||
                y >= FEEDBACK_DISPLAY_HEIGHT) {
                return;
            }
            ((DWORD *)m_Bits)[m_Width*y + x] = color;
        }
        inline void SetPixelFast(unsigned int x, unsigned int y, DWORD color) {
            ((DWORD *)m_Bits)[m_Width*y + x] = color;
        }
        void DrawRectangle(unsigned int x, 
                           unsigned int y, 
                           unsigned int width, 
                           unsigned int height,
                           DWORD color);
	    void DrawBar(unsigned int x, 
                     unsigned int y, 
		             unsigned int bar_value, 
                     unsigned int bar_width,
				     unsigned int peak_value,
				     unsigned int peak_height);
        void Paint(int x, int y);

    	DWORD       *m_Bits;
        unsigned int m_Width;
        unsigned int m_Height;

private:
    HDC          m_DC;
	BITMAPINFO   m_BitmapInfo;
};

class Band {
public:
	     Band(unsigned int width=8,
			  unsigned int peak_bar_thickness = 3,
              unsigned int band_range = 64) : 
			 m_Width(width), 
			 m_Value(0),
             m_Decay(0),
			 m_Peak(0), 
			 m_PeakBarThickness(peak_bar_thickness),
             m_Range(band_range) {};
	void Paint(PaintBox &box, int x, int y);
	void SetValue(unsigned int value);
    void SetWidth(unsigned int width) { m_Width = width; };
    void SetRange(unsigned int range) { m_Range = range; };
	
private:
	unsigned int  m_Width;
	unsigned int  m_Value;
    unsigned int  m_Range;
    unsigned int  m_Decay;
	unsigned int  m_Peak;
	unsigned int  m_PeakBarThickness;
};

class BandDisplay {
public:
	     BandDisplay(PaintBox &box,
                     unsigned int nb_bands = 32,
                     unsigned int band_width = 6,
                     unsigned int band_spacing = 1,
                     unsigned int band_range = 64);
	    ~BandDisplay();
	void Paint(int x, int y);
	void SetBandValue(unsigned int band, unsigned int value);

private:
    PaintBox    &m_PaintBox;
	unsigned int m_NbBands;
	Band        *m_Bands;
    unsigned int m_BandWidth;
    unsigned int m_BandSpacing;
};

class LineDisplay {
public:
    LineDisplay(PaintBox &box,
                unsigned int width = 128,
                unsigned int height = 64);
    ~LineDisplay();
     void Paint(int x, int y);
     void SetPoint(unsigned int x, unsigned int y);

private:
    PaintBox     &m_PaintBox;
    unsigned int *m_Points;
    unsigned int  m_Width;
    unsigned int  m_Height;
};

class HandlerException {};

struct XA_FeedbackHandlerInstance {};
class Handler : public XA_FeedbackHandlerInstance {
public:
    Handler(HWND window, unsigned int width, unsigned int height);
    virtual ~Handler() {};
    virtual void ProcessEvent(XA_AudioEvent *event) = 0;
    PaintBox m_PaintBox;

protected:
    HWND m_Window;
};

class SpectrumHandler : public Handler {
public:
    SpectrumHandler(HWND window, unsigned int width, unsigned int height);
    virtual ~SpectrumHandler();
    void ProcessEvent(XA_AudioEvent *event);

private:
    struct {
        XA_FftAnalyzer *analyzer;
        BandDisplay    *display;
        unsigned char   values[FEEDBACK_NB_BANDS];
    } m_Left;
    struct {
        XA_FftAnalyzer *analyzer;
        BandDisplay    *display;
        unsigned char   values[FEEDBACK_NB_BANDS];
    } m_Right;
};

class VUHandler : public Handler {
public:
    VUHandler(HWND window, unsigned int width, unsigned int height);
    virtual ~VUHandler();
    void ProcessEvent(XA_AudioEvent *event);

private:
    BandDisplay *m_Display;
};

class OscilloscopeHandler : public Handler {
public:
    OscilloscopeHandler(HWND window, unsigned int width, unsigned int height);
    virtual ~OscilloscopeHandler();
    void ProcessEvent(XA_AudioEvent *event);

private:
    LineDisplay *m_Display;
};

/*----------------------------------------------------------------------
|       Handler::Handler
+---------------------------------------------------------------------*/
Handler::Handler(HWND         window,
                 unsigned int width, 
                 unsigned int height) :
                 m_Window(window),
                 m_PaintBox(GetDC(window), width, height)
{
}

/*----------------------------------------------------------------------
|       SpectrumHandler::SpectrumHandler
+---------------------------------------------------------------------*/
SpectrumHandler::SpectrumHandler(HWND         window,
                                 unsigned int width, 
                                 unsigned int height) :
                 Handler(window, width, height)
{
    // create display objects
    m_Left.display  = new BandDisplay(m_PaintBox, FEEDBACK_NB_BANDS, 4);
    m_Right.display = new BandDisplay(m_PaintBox, FEEDBACK_NB_BANDS, 4);

    // allocate 2 fft analyzers
    int status;
    status = fft_analyzer_new(&m_Left.analyzer);
    if (status) throw HandlerException();
    status = fft_analyzer_new(&m_Right.analyzer);
    if (status) {
        fft_analyzer_delete(m_Left.analyzer);
        throw HandlerException();
    }
}

/*----------------------------------------------------------------------
|       SpectrumHandler::~SpectrumHandler
+---------------------------------------------------------------------*/
SpectrumHandler::~SpectrumHandler()
{
    // delete displays
    delete m_Left.display;
    delete m_Right.display;

    // delete analyzers
    fft_analyzer_delete(m_Left.analyzer);
    fft_analyzer_delete(m_Right.analyzer);
}

#include <math.h>

/*----------------------------------------------------------------------
|       SpectrumHandler::ProcessEvent
+---------------------------------------------------------------------*/
void
SpectrumHandler::ProcessEvent(XA_AudioEvent *event)
{
    int nb_samples;

    // compute number of samples needed for computation
    if (event->nb_samples > FEEDBACK_NB_BANDS*2) {
        nb_samples = FEEDBACK_NB_BANDS*2;
    } else {
        nb_samples = event->nb_samples;
    }

    // convert data format
    if (event->nb_channels == 2) {
        fft_analyzer_set_samples(m_Left.analyzer, 
                                 event->samples,
                                 nb_samples);
        fft_analyzer_set_samples(m_Right.analyzer, 
                                 event->samples + event->nb_samples,
                                 nb_samples);
        fft_analyzer_get_spectrum(m_Left.analyzer,
                                  m_Left.values,
                                  FEEDBACK_NB_BANDS);
        fft_analyzer_get_spectrum(m_Right.analyzer,
                                  m_Right.values,
                                  FEEDBACK_NB_BANDS);
    } else {
        fft_analyzer_set_samples(m_Left.analyzer, 
                                 event->samples,
                                 nb_samples);
        fft_analyzer_get_spectrum(m_Left.analyzer,
                                  m_Left.values,
                                  FEEDBACK_NB_BANDS);
    }

    // set band values 
    for (int i=1; i<FEEDBACK_NB_BANDS; i++) {
        m_Left.display->SetBandValue(i-1, m_Left.values[i]/2);
    }

    // here we should display the right channel, but there is not space on the screen

    m_Left.display->Paint(0, FEEDBACK_DISPLAY_HEIGHT);
}

/*----------------------------------------------------------------------
|       VUHandler::VUHandler
+---------------------------------------------------------------------*/
VUHandler::VUHandler(HWND         window,
                     unsigned int width, 
                     unsigned int height) :
           Handler(window, width, height)
{
    // create display objects
    m_Display = new BandDisplay(m_PaintBox, 2, 32, 4);
}

/*----------------------------------------------------------------------
|       VUHandler::~UHandler
+---------------------------------------------------------------------*/
VUHandler::~VUHandler()
{
    // delete display
    delete m_Display;
}

/*----------------------------------------------------------------------
|       VUHandler::ProcessEvent
+---------------------------------------------------------------------*/
void
VUHandler::ProcessEvent(XA_AudioEvent *event)
{
    int vu_peak_left = 0;
    int vu_peak_right = 0;
    for (int i=0; i<event->nb_samples; i++) {
        if (event->samples[i] > vu_peak_left) {
            vu_peak_left = event->samples[i];
        }
        if (event->samples[i+event->nb_samples] > vu_peak_right) {
            vu_peak_right = event->samples[i+event->nb_samples];
        }
    }
    m_Display->SetBandValue(0, vu_peak_left);
    m_Display->SetBandValue(1, vu_peak_right);
    m_Display->Paint(0, FEEDBACK_DISPLAY_HEIGHT);
}

/*----------------------------------------------------------------------
|       OscilloscopeHandler::OscilloscopeHandler
+---------------------------------------------------------------------*/
OscilloscopeHandler::OscilloscopeHandler(HWND         window,
                                         unsigned int width, 
                                         unsigned int height) :
                     Handler(window, width, height)
{
    // create display objects
    m_Display = new LineDisplay(m_PaintBox,
                                FEEDBACK_DISPLAY_WIDTH,
                                FEEDBACK_DISPLAY_HEIGHT);
}

/*----------------------------------------------------------------------
|       OscilloscopeHandler::~OscilloscopeHandler
+---------------------------------------------------------------------*/
OscilloscopeHandler::~OscilloscopeHandler()
{
    // delete display
    delete m_Display;
}

/*----------------------------------------------------------------------
|       OscilloscopeHandler::ProcessEvent
+---------------------------------------------------------------------*/
void
OscilloscopeHandler::ProcessEvent(XA_AudioEvent *event)
{
    for (int i=0; 
         i<(event->nb_samples < FEEDBACK_DISPLAY_WIDTH ? 
                                event->nb_samples : 
                                FEEDBACK_DISPLAY_WIDTH); 
         i++) {
        m_Display->SetPoint(i, FEEDBACK_DISPLAY_HEIGHT/2+
            (event->samples[i]*FEEDBACK_DISPLAY_HEIGHT)/256);
    }
    m_Display->Paint(0, FEEDBACK_DISPLAY_HEIGHT);
}

/*----------------------------------------------------------------------
|       PaintBox::PaintBox
+---------------------------------------------------------------------*/
PaintBox::PaintBox(HDC          dc,
                   unsigned int width, 
                   unsigned int height) :
                   m_Bits(new DWORD[width*height]),
                   m_Width(width),
                   m_Height(height),
                   m_DC(dc)
{
    // create DIB Section
    m_BitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
    m_BitmapInfo.bmiHeader.biWidth         = width; 
    m_BitmapInfo.bmiHeader.biHeight        = height; 
    m_BitmapInfo.bmiHeader.biPlanes        = 1; 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?