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 + -
显示快捷键?