begin process at 2010 02 10 15:24:32
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Multimédia

 > [ FMOD | WXWIDGETS]RENDU SPECTRUM -- MP3

[ FMOD | WXWIDGETS]RENDU SPECTRUM -- MP3


 Information sur la source

Note :
8,5 / 10 - par 2 personnes
8,50 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Multimédia Classé sous :wxwidgets, fmod, spectre, audio Niveau :Débutant Date de création :09/04/2006 Date de mise à jour :13/04/2006 18:47:19 Vu / téléchargé :6 659 / 636

Auteur : satellite34

Ecrire un message privé
Site perso
Commentaire sur cette source (13)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
voila, un tout petit projet sympa, lit les fichiers audio, affiche un spectre, pour débutants...

le spectre a été développé avec une mackie cfx20 ( je me suis bien fait ch** ), normalement assez fidéle.

Cela dit, ce programme peux constituer un bon exemple a tout débutant wxWIDGETS ou meme FMOD;

Le rendu est opéré dans des threads séparés avec des wxMemoryDC.

Ce programme ne marche probablement que sous windows, enfin, je dis ca car je n'ai rien fait pour la portabilité, a tester donc...

voila, pas d'améliorations prévues, mais toute remarque sera la bienvenue;
Enjoy

Source

  • // main.cpp [ seul et unique fichier ]
  • #include <wx/wxprec.h>
  • #ifdef __BORLANDC__
  • #pragma hdrstop
  • #endif
  • #ifndef WX_PRECOMP
  • #include <wx/wx.h>
  • #endif
  • #include <fmod.h>
  • #include <fmod_errors.h>
  • #include <fstream>
  • WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
  • #define ZONESPECTRE_WIDTH 350
  • #define ZONESPECTRE_HEIGHT 116
  • class MyFrame;
  • class ControlWin;
  • class MyRenderThread;
  • class MyControlThread;
  • class MyLevelThread;
  • class PaneControl : public wxFrame
  • {
  • DECLARE_EVENT_TABLE()
  • public:
  • PaneControl(MyFrame *m_parent);
  • virtual ~PaneControl();
  • MyFrame *m_pFrame;
  • MyLevelThread *CreateLevelThread(void);
  • void StartLevelThread(void);
  • private:
  • void PaintInitialScreen(wxDC &dc);
  • protected:
  • void OnPaint(wxPaintEvent &event);
  • };
  • class MyLevelThread : public wxThread
  • {
  • PaneControl *m_pPaneWin;
  • MyFrame *m_pFrame;
  • ControlWin *m_pControlWin;
  • public:
  • MyLevelThread(PaneControl *m_paneWindow, MyFrame *m_frame, ControlWin *m_controlwin);
  • virtual void *Entry(void);
  • virtual void OnExit(void);
  • void RenderPane(wxDC &dc);
  • };
  • class ControlWin : public wxFrame
  • {
  • DECLARE_EVENT_TABLE()
  • public:
  • ControlWin(MyFrame *m_parent);
  • virtual ~ControlWin();
  • MyFrame *m_pFrame;
  • MyControlThread *CreateControlThread(void);
  • void StartControlThread(void);
  • private:
  • void PaintInitialScreen(wxDC &dc);
  • protected:
  • void OnPaint(wxPaintEvent &event);
  • };
  • class DSPWnd : public wxWindow
  • {
  • DECLARE_EVENT_TABLE()
  • public:
  • DSPWnd(MyFrame *m_parent);
  • virtual ~DSPWnd();
  • MyFrame *m_pFrame;
  • MyRenderThread *CreateRenderThread(void);
  • void StartRenderThread(void);
  • void PaintInitialScreen(wxDC &dc);
  • protected:
  • void OnPaint(wxPaintEvent &event);
  • void OnSize(wxSizeEvent &event);
  • };
  • class MyControlThread : public wxThread
  • {
  • ControlWin *m_pControlWin;
  • MyFrame *m_pFrame;
  • public:
  • MyControlThread(ControlWin *m_controlwin, MyFrame *m_frame);
  • virtual void *Entry(void);
  • virtual void OnExit(void);
  • void RenderInfos(wxDC &dc);
  • };
  • class MyRenderThread : public wxThread
  • {
  • DSPWnd *m_pRenderWin;
  • ControlWin *m_pControlWin;
  • MyFrame *m_pFrame;
  • public:
  • MyRenderThread(MyFrame *m_frame, DSPWnd *m_renderwin, ControlWin *m_controlwin);
  • virtual void *Entry(void);
  • virtual void OnExit(void);
  • void RenderSpectrum(wxDC &dc, bool uselog);
  • bool IsFinished;
  • };
  • class MyApp : public wxApp
  • {
  • public:
  • MyApp();
  • virtual bool OnInit();
  • wxCriticalSection m_critsect;
  • wxSemaphore m_semAllDone;
  • bool m_waitingUntilAllDone;
  • wxArrayThread m_threads;
  • };
  • DECLARE_APP(MyApp)
  • class MyFrame : public wxFrame
  • {
  • DECLARE_EVENT_TABLE()
  • public:
  • DSPWnd *m_pRenderWin;
  • ControlWin *m_pControlWin;
  • PaneControl *m_pPaneControl;
  • FSOUND_STREAM *m_pStream;
  • bool IsQuit;
  • bool IsFinished;
  • int channel;
  • char *data;
  • MyFrame();
  • virtual ~MyFrame();
  • private:
  • void PlayFile(const wxString &filename);
  • protected:
  • void OnClose(wxCloseEvent &event);
  • void OnDrop(wxDropFilesEvent &event);
  • };
  • MyApp::MyApp() : m_semAllDone()
  • {
  • m_waitingUntilAllDone = false;
  • }
  • bool MyApp::OnInit()
  • {
  • int width, height, x, y;
  • wxClientDisplayRect(&x, &y, &width, &height);
  • wxPoint m_point(width-ZONESPECTRE_WIDTH, height-200);
  • MyFrame *frame = new MyFrame;
  • frame->SetSize(ZONESPECTRE_WIDTH, 200);
  • frame->SetPosition(m_point);
  • frame->Show(true);
  • return true;
  • }
  • MyLevelThread::MyLevelThread(PaneControl *m_paneWindow, MyFrame *m_frame, ControlWin *m_controlwin) : wxThread()
  • {
  • m_pFrame = m_frame;
  • m_pPaneWin = m_paneWindow;
  • m_pControlWin = m_controlwin;
  • }
  • void *MyLevelThread::Entry(void)
  • {
  • if( TestDestroy() )
  • return NULL;
  • wxWindowDC dc(m_pPaneWin);
  • RenderPane(dc);
  • return NULL;
  • }
  • void MyLevelThread::OnExit(void)
  • {
  • wxCriticalSectionLocker locker( wxGetApp().m_critsect );
  • wxArrayThread& threads = wxGetApp().m_threads;
  • threads.Remove(this);
  • if( threads.IsEmpty() )
  • {
  • if( wxGetApp().m_waitingUntilAllDone )
  • {
  • wxGetApp().m_waitingUntilAllDone = false;
  • wxGetApp().m_semAllDone.Post();
  • }
  • }
  • if( !m_pFrame->IsQuit && !m_pFrame->IsFinished )
  • {
  • m_pPaneWin->StartLevelThread();
  • }
  • }
  • void MyLevelThread::RenderPane(wxDC &dc)
  • {
  • #define offset(_x) (y - 20) - _x
  • Sleep( 24 );
  • int time = FSOUND_Stream_GetTime(m_pFrame->m_pStream);
  • int length = FSOUND_Stream_GetLengthMs(m_pFrame->m_pStream);
  • if( time == length || m_pFrame->IsQuit )
  • {
  • m_pFrame->IsFinished = true;
  • return;
  • }
  • float l, r;
  • int R, G, B, x, y, MyLevelL, MyLevelR;
  • m_pPaneWin->GetClientSize(&x, &y);
  • FSOUND_GetCurrentLevels(m_pFrame->channel, &l, &r);
  • MyLevelL = (int) (l * 100.0f);
  • MyLevelR = (int) (r * 100.0f);
  • wxBitmap bmp(x-20, y-15);
  • wxMemoryDC memdc;
  • memdc.SelectObject( bmp );
  • dc.SetDeviceOrigin( 3, 35 );
  • for( int l = x/2 - 12; l < ( x/2 - 12 ) + 10; l++)
  • {
  • for( int h = 0; h < MyLevelL; h++ )
  • {
  • R = h << 1;
  • G = 0xFF - (h << 1);
  • B = 0x1F;
  • if( R <= 0xFF && G <= 0xFF )
  • memdc.SetPen( wxColour(R, G, B) );
  • else memdc.SetPen( *wxRED );
  • memdc.BeginDrawing();
  • memdc.DrawPoint( l, offset(h) );
  • memdc.EndDrawing();
  • }
  • }
  • for( int l = x/2; l < x/2 + 10; l++)
  • {
  • for( int h = 0; h < MyLevelR; h++ )
  • {
  • if( MyLevelR >= y - 15)
  • MyLevelR = y - 16;
  • R = h << 1;
  • G = 0xFF - (h << 1);
  • B = 0x1F;
  • if( R <= 0xFF && G <= 0xFF )
  • memdc.SetPen( wxColour(R, G, B) );
  • else memdc.SetPen( *wxRED );
  • memdc.BeginDrawing();
  • memdc.DrawPoint( l, offset(h) );
  • memdc.EndDrawing();
  • }
  • }
  • dc.Blit(0, 0, x, y, &memdc, 0, 0);
  • wxMemoryDC mmdc;
  • wxBitmap mmbmp(120, 12);
  • mmdc.SelectObject(mmbmp);
  • mmdc.SetFont(*wxITALIC_FONT);
  • mmdc.SetTextForeground( *wxLIGHT_GREY );
  • wxString str;
  • str.Printf("Thread 0x%lx DSPP run", GetId());
  • mmdc.DrawText(str, 1, 0);
  • wxWindowDC Cdc(m_pControlWin);
  • Cdc.Blit( 3, 138, 120, 12, &mmdc, 0, 0, wxCOPY );
  • }
  • MyControlThread::MyControlThread(ControlWin *m_controlwin, MyFrame *m_frame) : wxThread()
  • {
  • m_pFrame = m_frame;
  • m_pControlWin = m_controlwin;
  • }
  • void *MyControlThread::Entry(void)
  • {
  • if( TestDestroy() )
  • return NULL;
  • wxWindowDC dc(m_pControlWin);
  • RenderInfos(dc);
  • return NULL;
  • }
  • void MyControlThread::OnExit(void)
  • {
  • wxCriticalSectionLocker locker( wxGetApp().m_critsect );
  • wxArrayThread& threads = wxGetApp().m_threads;
  • threads.Remove(this);
  • if( threads.IsEmpty() )
  • {
  • if( wxGetApp().m_waitingUntilAllDone )
  • {
  • wxGetApp().m_waitingUntilAllDone = false;
  • wxGetApp().m_semAllDone.Post();
  • }
  • }
  • if( !m_pFrame->IsQuit && !m_pFrame->IsFinished )
  • {
  • m_pControlWin->StartControlThread();
  • }
  • }
  • void MyControlThread::RenderInfos(wxDC &dc)
  • {
  • Sleep(20);
  • float RIGHT, LEFT;
  • int time = FSOUND_Stream_GetTime(m_pFrame->m_pStream);
  • int length = FSOUND_Stream_GetLengthMs(m_pFrame->m_pStream);
  • if( time == length || m_pFrame->IsQuit )
  • {
  • m_pFrame->IsFinished = true;
  • return;
  • }
  • wxString status, cpu, cput, rate, memorystats, Rlevel, Llevel, threads;
  • unsigned int currentalloced, maxalloced;
  • float m_cpuf = FSOUND_GetCPUUsage();
  • int irate = FSOUND_GetFrequency(m_pFrame->channel);
  • FSOUND_GetCurrentLevels(m_pFrame->channel, &RIGHT, &LEFT);
  • FSOUND_GetMemoryStats(&currentalloced,&maxalloced);
  • threads.Printf("Thread 0x%lx CTR run", GetId());
  • Rlevel.Printf("Rlevel : %f", RIGHT*10);
  • Llevel.Printf("Llevel : %f", LEFT*10);
  • memorystats.Printf("Mem alloced: %d", currentalloced);
  • rate.Printf("Rate: %dHZ", irate);
  • cpu.Printf("%f", m_cpuf);
  • cpu << " % CPU";
  • status.Printf("%d ms / %d", time, length);
  • int x, y;
  • m_pControlWin->GetClientSize(&x, &y);
  • wxBitmap bmp(x, y);
  • wxMemoryDC memdc;
  • memdc.SelectObject(bmp);
  • memdc.SetFont(*wxITALIC_FONT);
  • memdc.SetTextForeground( *wxLIGHT_GREY );
  • memdc.DrawText(status, 1, 0);
  • memdc.DrawText(cpu, 1, 12);
  • memdc.DrawText(rate, 1, 24);
  • memdc.DrawText(memorystats, 1, 36);
  • memdc.DrawText(Rlevel, 1, 48);
  • memdc.DrawText(Llevel, 1, 60);
  • memdc.DrawText(threads, 1, 72);
  • dc.Blit(3, 42, x-6, 84, &memdc, 0, 0);
  • }
  • MyRenderThread::MyRenderThread(MyFrame *m_frame, DSPWnd *m_renderwin, ControlWin *m_controlwin) : wxThread( )
  • {
  • m_pFrame = m_frame;
  • m_pRenderWin = m_renderwin;
  • m_pControlWin = m_controlwin;
  • }
  • void *MyRenderThread::Entry(void)
  • {
  • if( TestDestroy() )
  • return NULL;
  • wxWindowDC m_dc( m_pRenderWin );
  • RenderSpectrum(m_dc, true);
  • return NULL;
  • }
  • void MyRenderThread::OnExit(void)
  • {
  • wxCriticalSectionLocker locker(wxGetApp().m_critsect);
  • wxArrayThread& threads = wxGetApp().m_threads;
  • threads.Remove(this);
  • if( threads.IsEmpty() )
  • {
  • if( wxGetApp().m_waitingUntilAllDone )
  • {
  • wxGetApp().m_waitingUntilAllDone = false;
  • wxGetApp().m_semAllDone.Post();
  • }
  • }
  • if( !m_pFrame->IsQuit && !m_pFrame->IsFinished )
  • {
  • m_pRenderWin->StartRenderThread();
  • }
  • }
  • void MyRenderThread::RenderSpectrum(wxDC &dc, bool uselog)
  • {
  • Sleep(25);
  • int x, y;
  • int r, g, b, ampli;
  • float max, val, db;
  • int time = FSOUND_Stream_GetTime(m_pRenderWin->m_pFrame->m_pStream);
  • int length = FSOUND_Stream_GetLengthMs(m_pRenderWin->m_pFrame->m_pStream);
  • if( time == length || m_pRenderWin->m_pFrame->IsQuit )
  • {
  • m_pRenderWin->m_pFrame->IsFinished = true;
  • m_pRenderWin->PaintInitialScreen( dc );
  • return;
  • }
  • m_pRenderWin->GetClientSize(&x, &y);
  • dc.SetDeviceOrigin(15, 0);
  • wxBitmap bmp(x - 15, y - 12);
  • wxMemoryDC memdc;
  • memdc.SelectObject(bmp);
  • float *m_spectr = FSOUND_DSP_GetSpectrum();
  • /*
  • 1.0 = 0db
  • 0.5 = -6db
  • 0.25 = -12db
  • 0.125 = -24db
  • */
  • max = 0.0f;
  • for(int i = 0; i < x; i++)
  • {
  • if( x > 512 + ( i * 10 ) )
  • x = 512 + (i * 10);
  • /*
  • val = ( m_spectr[i] +
  • m_spectr[i+1] +
  • m_spectr[i+2] +
  • m_spectr[i+3] +
  • m_spectr[i+4] +
  • m_spectr[i+6] +
  • m_spectr[i+7] +
  • m_spectr[i+8] +
  • m_spectr[i+9] ) / 10;
  • */
  • val = m_spectr[i];
  • if( val > max )
  • max = val;
  • if(uselog)
  • {
  • db = 10.0f * (float)log10(val) * 2.0f;
  • val = db;
  • if (val < -150)
  • {
  • val = -150;
  • }
  • val /= -150.0f;
  • val = 1.0f - val;
  • ampli = (int)( val * (float)ZONESPECTRE_HEIGHT );
  • }
  • else
  • {
  • ampli = (int)( val / max * (float)ZONESPECTRE_HEIGHT );
  • }
  • for(int j = ampli - 10; j < ampli; j++)
  • {
  • r = j << 1;
  • g = 0xFF - (j << 1);
  • b = 0x1F;
  • if( r <= 0xFF && g <= 0xFF )
  • memdc.SetPen( wxColour(r, g, b) );
  • else memdc.SetPen( *wxRED );
  • #define AMPLITUDE(_x) (y - 12) - _x
  • memdc.BeginDrawing();
  • for(int l = i; l < i + 10; l++)
  • {
  • memdc.DrawPoint( l, AMPLITUDE( j ) );
  • }
  • memdc.EndDrawing();
  • }
  • i = i + 10;
  • }
  • memdc.SetPen(wxNullPen);
  • dc.Blit( 0, 0, x, y, &memdc, 0, 0, wxCOPY );
  • wxMemoryDC mmdc;
  • wxBitmap mmbmp(120, 12);
  • mmdc.SelectObject(mmbmp);
  • mmdc.SetFont(*wxITALIC_FONT);
  • mmdc.SetTextForeground( *wxLIGHT_GREY );
  • wxString str;
  • str.Printf("Thread 0x%lx DSP run", GetId());
  • mmdc.DrawText(str, 1, 0);
  • wxWindowDC Cdc(m_pControlWin);
  • Cdc.Blit( 3, 126, 110, 12, &mmdc, 0, 0, wxCOPY );
  • }
  • BEGIN_EVENT_TABLE(PaneControl, wxFrame)
  • EVT_PAINT(PaneControl::OnPaint)
  • END_EVENT_TABLE()
  • PaneControl::PaneControl(MyFrame *m_parent) : wxFrame ( NULL,
  • wxID_ANY,
  • wxEmptyString,
  • wxDefaultPosition,
  • wxSize(75, 160),
  • wxCAPTION |
  • wxMINIMIZE_BOX |
  • //wxSTAY_ON_TOP |
  • wxSYSTEM_MENU |
  • wxFRAME_TOOL_WINDOW |
  • wxNO_BORDER ), m_pFrame(m_parent)
  • {
  • SetBackgroundColour(*wxBLACK);
  • SetTitle(_T("Levels"));
  • int width, height, x, y;
  • wxClientDisplayRect(&x, &y, &width, &height);
  • wxPoint m_point(width - ZONESPECTRE_WIDTH - 130 - 75, height-160);
  • SetPosition(m_point);
  • Show( true );
  • }
  • PaneControl::~PaneControl()
  • {
  • }
  • void PaneControl::OnPaint(wxPaintEvent &WXUNUSED(event))
  • {
  • wxPaintDC m_dc(this);
  • m_dc.Clear();
  • PaintInitialScreen(m_dc);
  • }
  • void PaneControl::PaintInitialScreen(wxDC &dc)
  • {
  • dc.SetFont(wxFont(8, wxTELETYPE, wxNORMAL, wxNORMAL) );
  • dc.SetTextForeground( *wxGREEN );
  • dc.DrawText("LEVELS", 1, 1 );
  • }
  • MyLevelThread *PaneControl::CreateLevelThread( void )
  • {
  • MyLevelThread *thread = new MyLevelThread(this, m_pFrame, m_pFrame->m_pControlWin);
  • if ( thread->Create() != wxTHREAD_NO_ERROR )
  • {
  • wxLogError(_T("Can't create thread!"));
  • }
  • wxCriticalSectionLocker enter( wxGetApp().m_critsect );
  • wxGetApp().m_threads.Add(thread);
  • return thread;
  • }
  • void PaneControl::StartLevelThread( void )
  • {
  • wxThread *thr = CreateLevelThread();
  • if ( thr->Run() != wxTHREAD_NO_ERROR )
  • {
  • wxLogError(wxT("Can't start thread!"));
  • }
  • thr->SetPriority(WXTHREAD_DEFAULT_PRIORITY);
  • }
  • BEGIN_EVENT_TABLE(ControlWin, wxFrame)
  • EVT_PAINT(ControlWin::OnPaint)
  • END_EVENT_TABLE()
  • ControlWin::ControlWin(MyFrame *m_parent) : wxFrame ( NULL,
  • wxID_ANY,
  • wxEmptyString,
  • wxDefaultPosition,
  • wxSize(130, 200),
  • wxCAPTION |
  • wxMINIMIZE_BOX |
  • wxSYSTEM_MENU |
  • wxFRAME_TOOL_WINDOW |
  • wxNO_BORDER ), m_pFrame(m_parent)
  • {
  • int width, height, x, y;
  • wxClientDisplayRect(&x, &y, &width, &height);
  • wxPoint m_point(width - ZONESPECTRE_WIDTH - 130, height-200);
  • SetPosition(m_point);
  • SetTitle(_T("Controler"));
  • SetBackgroundColour(*wxBLACK);
  • Show( true );
  • }
  • ControlWin::~ControlWin()
  • {
  • }
  • void ControlWin::OnPaint(wxPaintEvent &WXUNUSED(event))
  • {
  • wxPaintDC dc( this );
  • PaintInitialScreen( dc );
  • }
  • void ControlWin::PaintInitialScreen(wxDC &dc)
  • {
  • dc.SetFont(wxFont(8, wxTELETYPE, wxNORMAL, wxNORMAL) );
  • dc.SetTextForeground( *wxGREEN );
  • dc.DrawText("CONTROLER", 1, 1 );
  • }
  • MyControlThread *ControlWin::CreateControlThread(void)
  • {
  • MyControlThread *thread = new MyControlThread(this, m_pFrame);
  • if ( thread->Create() != wxTHREAD_NO_ERROR )
  • {
  • wxLogError(_T("Can't create thread!"));
  • }
  • wxCriticalSectionLocker enter( wxGetApp().m_critsect );
  • wxGetApp().m_threads.Add(thread);
  • return thread;
  • }
  • void ControlWin::StartControlThread(void)
  • {
  • wxThread *thr = CreateControlThread();
  • if ( thr->Run() != wxTHREAD_NO_ERROR )
  • {
  • wxLogError(wxT("Can't start thread!"));
  • }
  • thr->SetPriority(WXTHREAD_MIN_PRIORITY);
  • }
  • BEGIN_EVENT_TABLE(DSPWnd, wxWindow)
  • EVT_PAINT(DSPWnd::OnPaint)
  • EVT_SIZE(DSPWnd::OnSize)
  • END_EVENT_TABLE()
  • DSPWnd::DSPWnd(MyFrame *m_parent) : wxWindow( m_parent,
  • wxID_ANY,
  • wxPoint(-1,-1),
  • wxSize(-1,-1),
  • NULL,
  • "" ), m_pFrame(m_parent)
  • {
  • SetBackgroundColour(*wxBLACK);
  • FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), true);
  • if( !FSOUND_DSP_GetActive( FSOUND_DSP_GetFFTUnit() ) )
  • {
  • wxLogError("Can't active spctrum");
  • return;
  • }
  • }
  • DSPWnd::~DSPWnd()
  • {
  • }
  • void DSPWnd::PaintInitialScreen(wxDC &dc)
  • {
  • int w, h, db, freq;
  • wxString sDb, sFreq;
  • GetClientSize(&w, &h);
  • db = -24;
  • freq = 0;
  • dc.Clear();
  • dc.SetPen(*wxWHITE);
  • dc.SetFont( wxFont(5, wxSWISS, wxNORMAL, wxNORMAL) );
  • dc.SetTextForeground( *wxWHITE );
  • for(int i = 15; i < w; i++)
  • {
  • dc.DrawLine(i, h-2, i, h);
  • i = i + 2;
  • }
  • for(int i = 5; i < h-10; i++)
  • {
  • dc.DrawLine(0, i, 2, i);
  • i = i + 2;
  • }
  • for(int i = h; i > 0; i--)
  • {
  • i = i - 16;
  • if(db <= 0)
  • {
  • sDb.Printf("%d", db);
  • }
  • else
  • {
  • sDb.Printf("+%d", db);
  • }
  • dc.DrawText( sDb, 3.2f, i );
  • db = db + 4;
  • }
  • for(int i = 13; i < w; i++)
  • {
  • sFreq.Printf("%d", freq);
  • dc.DrawText( sFreq, i, h-10 );
  • freq = i * (float)43.06640625f;
  • i = i + 23;
  • }
  • }
  • void DSPWnd::OnPaint(wxPaintEvent &WXUNUSED(event))
  • {
  • wxPaintDC dc(this);
  • PaintInitialScreen( dc );
  • }
  • void DSPWnd::OnSize(wxSizeEvent &WXUNUSED(event))
  • {
  • Refresh();
  • }
  • MyRenderThread *DSPWnd::CreateRenderThread()
  • {
  • MyRenderThread *thread = new MyRenderThread(m_pFrame, this, m_pFrame->m_pControlWin);
  • if ( thread->Create() != wxTHREAD_NO_ERROR )
  • {
  • wxLogError(_T("Can't create thread!"));
  • }
  • wxCriticalSectionLocker enter( wxGetApp().m_critsect );
  • wxGetApp().m_threads.Add(thread);
  • return thread;
  • }
  • void DSPWnd::StartRenderThread(void)
  • {
  • wxThread *thr = CreateRenderThread();
  • if ( thr->Run() != wxTHREAD_NO_ERROR )
  • {
  • wxLogError(wxT("Can't start thread!"));
  • }
  • size_t n = wxGetApp().m_threads.GetCount();
  • if ( n == 0 )
  • thr->SetPriority(WXTHREAD_MIN_PRIORITY);
  • else if ( n == 1 )
  • thr->SetPriority(WXTHREAD_MAX_PRIORITY);
  • else
  • thr->SetPriority(WXTHREAD_DEFAULT_PRIORITY);
  • }
  • IMPLEMENT_APP(MyApp)
  • BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  • EVT_CLOSE(MyFrame::OnClose)
  • EVT_DROP_FILES(MyFrame::OnDrop)
  • END_EVENT_TABLE()
  • MyFrame::MyFrame() : wxFrame( NULL,
  • wxID_ANY,
  • _T("Spectrum"),
  • wxDefaultPosition,
  • wxDefaultSize,
  • wxCAPTION |
  • wxMINIMIZE_BOX |
  • wxSYSTEM_MENU |
  • wxCLOSE_BOX |
  • wxFRAME_TOOL_WINDOW )
  • {
  • m_pStream = NULL;
  • data = NULL;
  • IsQuit = false;
  • IsFinished = false;
  • channel = 0;
  • FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
  • if (FSOUND_GetVersion() < FMOD_VERSION)
  • {
  • wxLogError("Error : You are using the wrong DLL version! You should be using FMOD %.02f\n", FMOD_VERSION);
  • return;
  • }
  • if(!FSOUND_Init(44100, 32, NULL))
  • {
  • wxLogError("%s\n", FMOD_ErrorString(FSOUND_GetError()));
  • return;
  • }
  • FSOUND_Stream_SetBufferSize(100);
  • m_pControlWin = new ControlWin( this );
  • m_pRenderWin = new DSPWnd( this );
  • m_pPaneControl = new PaneControl( this );
  • DragAcceptFiles( true );
  • }
  • MyFrame::~MyFrame(void)
  • {
  • IsQuit = true;
  • IsFinished = true;
  • wxThread *thread;
  • wxGetApp().m_critsect.Enter();
  • const wxArrayThread& threads = wxGetApp().m_threads;
  • size_t count = threads.GetCount();
  • if ( count )
  • {
  • wxGetApp().m_waitingUntilAllDone = true;
  • while ( ! threads.IsEmpty() )
  • {
  • thread = threads.Last();
  • wxGetApp().m_critsect.Leave();
  • thread->Delete();
  • wxGetApp().m_critsect.Enter();
  • }
  • }
  • wxGetApp().m_critsect.Leave();
  • if ( count )
  • {
  • wxGetApp().m_semAllDone.Wait();
  • }
  • if( FSOUND_GetChannelsPlaying() > 0 )
  • FSOUND_Stream_Close(m_pStream);
  • FSOUND_Close();
  • m_pControlWin->Destroy();
  • m_pPaneControl->Destroy();
  • if( data )
  • delete [] data;
  • }
  • void MyFrame::OnClose(wxCloseEvent &WXUNUSED(event))
  • {
  • Destroy();
  • }
  • void MyFrame::OnDrop(wxDropFilesEvent &event)
  • {
  • IsFinished = true;
  • wxThread::Sleep( 5 );
  • wxString *arr;
  • wxString strstream;
  • arr = event.GetFiles();
  • strstream = arr[0];
  • PlayFile( strstream );
  • }
  • void MyFrame::PlayFile(const wxString &filename)
  • {
  • int length;
  • std::ifstream file;
  • file.open(filename, std::ios::binary );
  • file.seekg(0, std::ios::end);
  • length = file.tellg();
  • file.seekg(0, std::ios::beg);
  • data = new char[length];
  • file.read(data, length);
  • file.close();
  • if( FSOUND_GetChannelsPlaying() > 0 )
  • FSOUND_Stream_Close(m_pStream);
  • m_pStream = FSOUND_Stream_Open(data, FSOUND_NORMAL | FSOUND_MPEGACCURATE | FSOUND_LOADMEMORY, 0, length);
  • channel = FSOUND_Stream_PlayEx(FSOUND_FREE, m_pStream, NULL, false);
  • if(channel == -1)
  • {
  • wxLogError("Invalid Channel");
  • return;
  • }
  • IsFinished = false;
  • FSOUND_SetVolume(channel, 250);
  • FSOUND_SetSurround(channel, true);
  • if( wxGetApp().m_threads.IsEmpty() )
  • {
  • m_pRenderWin->StartRenderThread();
  • m_pPaneControl->StartLevelThread();
  • m_pControlWin->StartControlThread();
  • }
  • }
// main.cpp [ seul et unique fichier ]
#include <wx/wxprec.h>

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif

#include <fmod.h>
#include <fmod_errors.h>

#include <fstream>

WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);

#define ZONESPECTRE_WIDTH 350
#define ZONESPECTRE_HEIGHT 116

class MyFrame;
class ControlWin;
class MyRenderThread;
class MyControlThread;
class MyLevelThread;

class PaneControl : public wxFrame
{
	DECLARE_EVENT_TABLE()

public:
	PaneControl(MyFrame *m_parent);
	virtual ~PaneControl();

	MyFrame *m_pFrame;

	MyLevelThread *CreateLevelThread(void);

	void StartLevelThread(void);

private:
	void PaintInitialScreen(wxDC &dc);

protected:
	void OnPaint(wxPaintEvent &event);
};

class MyLevelThread : public wxThread
{
	PaneControl *m_pPaneWin;
	MyFrame     *m_pFrame;
	ControlWin  *m_pControlWin;

public:
	MyLevelThread(PaneControl *m_paneWindow, MyFrame *m_frame, ControlWin *m_controlwin);

	virtual void *Entry(void);

	virtual void OnExit(void);

	void RenderPane(wxDC &dc);
};

class ControlWin : public wxFrame
{
	DECLARE_EVENT_TABLE()

public:
	ControlWin(MyFrame *m_parent);
	virtual ~ControlWin();

	MyFrame *m_pFrame;

	MyControlThread *CreateControlThread(void);

	void StartControlThread(void);

private:
	void PaintInitialScreen(wxDC &dc);

protected:
	void OnPaint(wxPaintEvent &event);
};



class DSPWnd : public wxWindow
{
	DECLARE_EVENT_TABLE()

public:
	DSPWnd(MyFrame *m_parent);
	virtual ~DSPWnd();

	MyFrame *m_pFrame;

	MyRenderThread *CreateRenderThread(void);

	void StartRenderThread(void);

	void PaintInitialScreen(wxDC &dc);

protected:
	void OnPaint(wxPaintEvent &event);

	void OnSize(wxSizeEvent &event);
};



class MyControlThread : public wxThread
{
	ControlWin *m_pControlWin;
	MyFrame *m_pFrame;

public:
	MyControlThread(ControlWin *m_controlwin, MyFrame *m_frame);

	virtual void *Entry(void);

	virtual void OnExit(void);

	void RenderInfos(wxDC &dc);
};

class MyRenderThread : public wxThread
{
	DSPWnd *m_pRenderWin;
	ControlWin *m_pControlWin;
	MyFrame *m_pFrame;
	
public:
	MyRenderThread(MyFrame *m_frame, DSPWnd *m_renderwin, ControlWin *m_controlwin);

	virtual void *Entry(void);

	virtual void OnExit(void);

	void RenderSpectrum(wxDC &dc, bool uselog);

	bool IsFinished;
};



class MyApp : public wxApp
{
public:
	MyApp();
    virtual bool OnInit();

	wxCriticalSection m_critsect;

	wxSemaphore m_semAllDone;

	bool m_waitingUntilAllDone;
	
	wxArrayThread m_threads;
};



DECLARE_APP(MyApp)



class MyFrame : public wxFrame
{
	DECLARE_EVENT_TABLE()
	
public:
	DSPWnd        *m_pRenderWin;
	ControlWin    *m_pControlWin;
	PaneControl   *m_pPaneControl;

	FSOUND_STREAM *m_pStream;

	bool IsQuit;
	bool IsFinished;
	int channel;
	char *data;

    MyFrame();
	virtual ~MyFrame();

private:
	void PlayFile(const wxString &filename);

protected:
	void OnClose(wxCloseEvent &event);

	void OnDrop(wxDropFilesEvent &event);
};



MyApp::MyApp() : m_semAllDone()
{
	m_waitingUntilAllDone = false;
}



bool MyApp::OnInit()
{
	int width, height, x, y;

	wxClientDisplayRect(&x, &y, &width, &height);

	wxPoint m_point(width-ZONESPECTRE_WIDTH, height-200);

    MyFrame *frame = new MyFrame;

	frame->SetSize(ZONESPECTRE_WIDTH, 200);
	frame->SetPosition(m_point);

    frame->Show(true);
    return true;
}


MyLevelThread::MyLevelThread(PaneControl *m_paneWindow, MyFrame *m_frame, ControlWin *m_controlwin) : wxThread()
{
	m_pFrame      = m_frame;
	m_pPaneWin    = m_paneWindow;
	m_pControlWin = m_controlwin;
}

void *MyLevelThread::Entry(void)
{
	if( TestDestroy() )
		return NULL;

	wxWindowDC dc(m_pPaneWin);
	RenderPane(dc);

	return NULL;
}

void MyLevelThread::OnExit(void)
{
    wxCriticalSectionLocker locker( wxGetApp().m_critsect );

	wxArrayThread& threads = wxGetApp().m_threads;
    threads.Remove(this);

    if( threads.IsEmpty() )
    {
        if( wxGetApp().m_waitingUntilAllDone )
        {
            wxGetApp().m_waitingUntilAllDone = false;

            wxGetApp().m_semAllDone.Post();
        }
    }

	if( !m_pFrame->IsQuit && !m_pFrame->IsFinished )
	{
		m_pPaneWin->StartLevelThread();
	}
}

void MyLevelThread::RenderPane(wxDC &dc)
{
#define offset(_x) (y - 20) - _x
	
	Sleep( 24 );

	int   time           = FSOUND_Stream_GetTime(m_pFrame->m_pStream);
	int   length         = FSOUND_Stream_GetLengthMs(m_pFrame->m_pStream);
	if( time == length || m_pFrame->IsQuit )
	{
		m_pFrame->IsFinished = true;
		return;
	}	

	float l, r;
	int R, G, B, x, y, MyLevelL, MyLevelR;
	m_pPaneWin->GetClientSize(&x, &y);

	FSOUND_GetCurrentLevels(m_pFrame->channel, &l, &r);
	MyLevelL = (int) (l * 100.0f);
	MyLevelR = (int) (r * 100.0f);
	
	wxBitmap bmp(x-20, y-15);
	wxMemoryDC memdc;
	memdc.SelectObject( bmp );

	dc.SetDeviceOrigin( 3, 35 );

	for( int l = x/2 - 12; l < ( x/2 - 12 ) + 10; l++)
	{
		for( int h = 0; h < MyLevelL; h++ )
		{
			R = h << 1;
			G = 0xFF - (h << 1);
			B = 0x1F;

			if( R <= 0xFF && G <= 0xFF )
				memdc.SetPen( wxColour(R, G, B) );
			else memdc.SetPen( *wxRED );

			memdc.BeginDrawing();
			memdc.DrawPoint( l, offset(h) );
			memdc.EndDrawing();
		}
	}
	for( int l = x/2; l < x/2 + 10; l++)
	{
		for( int h = 0; h < MyLevelR; h++ )
		{
			if( MyLevelR >= y - 15)
				MyLevelR = y - 16;

			R = h << 1;
			G = 0xFF - (h << 1);
			B = 0x1F;

			if( R <= 0xFF && G <= 0xFF )
				memdc.SetPen( wxColour(R, G, B) );
			else memdc.SetPen( *wxRED );

			memdc.BeginDrawing();
			memdc.DrawPoint( l, offset(h) );
			memdc.EndDrawing();
		}
	}
	dc.Blit(0, 0, x, y, &memdc, 0, 0);

	wxMemoryDC mmdc;
	wxBitmap mmbmp(120, 12);
	mmdc.SelectObject(mmbmp);
	mmdc.SetFont(*wxITALIC_FONT);
    mmdc.SetTextForeground( *wxLIGHT_GREY );

	wxString str;
	str.Printf("Thread 0x%lx DSPP run", GetId());

	mmdc.DrawText(str, 1, 0);

	wxWindowDC Cdc(m_pControlWin);
	Cdc.Blit( 3, 138, 120, 12, &mmdc, 0, 0, wxCOPY );
}

MyControlThread::MyControlThread(ControlWin *m_controlwin, MyFrame *m_frame) : wxThread()
{
	m_pFrame = m_frame;
	m_pControlWin = m_controlwin;
}



void *MyControlThread::Entry(void)
{
	if( TestDestroy() )
		return NULL;

	wxWindowDC dc(m_pControlWin);
	RenderInfos(dc);

	return NULL;
}



void MyControlThread::OnExit(void)
{
    wxCriticalSectionLocker locker( wxGetApp().m_critsect );

	wxArrayThread& threads = wxGetApp().m_threads;
    threads.Remove(this);

    if( threads.IsEmpty() )
    {
        if( wxGetApp().m_waitingUntilAllDone )
        {
            wxGetApp().m_waitingUntilAllDone = false;

            wxGetApp().m_semAllDone.Post();
        }
    }

	if( !m_pFrame->IsQuit && !m_pFrame->IsFinished )
	{
		m_pControlWin->StartControlThread();
	}	
}



void MyControlThread::RenderInfos(wxDC &dc)
{
	Sleep(20);

	float RIGHT, LEFT;
	int   time           = FSOUND_Stream_GetTime(m_pFrame->m_pStream);
	int   length         = FSOUND_Stream_GetLengthMs(m_pFrame->m_pStream);
	if( time == length || m_pFrame->IsQuit )
	{
		m_pFrame->IsFinished = true;
		return;
	}	
	wxString status, cpu, cput, rate, memorystats, Rlevel, Llevel, threads;
	unsigned int currentalloced, maxalloced;

	float m_cpuf         = FSOUND_GetCPUUsage();
	int   irate          = FSOUND_GetFrequency(m_pFrame->channel);

	FSOUND_GetCurrentLevels(m_pFrame->channel, &RIGHT, &LEFT);

	FSOUND_GetMemoryStats(&currentalloced,&maxalloced);

	threads.Printf("Thread 0x%lx CTR run", GetId());

	Rlevel.Printf("Rlevel : %f", RIGHT*10);

	Llevel.Printf("Llevel : %f", LEFT*10);

	memorystats.Printf("Mem alloced: %d", currentalloced);

	rate.Printf("Rate: %dHZ", irate);

	cpu.Printf("%f", m_cpuf);
	cpu << " % CPU";

	status.Printf("%d ms / %d", time, length);

	int x, y;
	m_pControlWin->GetClientSize(&x, &y);

	wxBitmap bmp(x, y);
	wxMemoryDC memdc;
	memdc.SelectObject(bmp);

	memdc.SetFont(*wxITALIC_FONT);
    memdc.SetTextForeground( *wxLIGHT_GREY );

	memdc.DrawText(status,      1, 0);
	memdc.DrawText(cpu,         1, 12);
	memdc.DrawText(rate,        1, 24);
	memdc.DrawText(memorystats, 1, 36);
	memdc.DrawText(Rlevel,      1, 48);
	memdc.DrawText(Llevel,      1, 60);
	memdc.DrawText(threads,     1, 72);

	dc.Blit(3, 42, x-6, 84, &memdc, 0, 0);
}



MyRenderThread::MyRenderThread(MyFrame *m_frame, DSPWnd *m_renderwin, ControlWin *m_controlwin) : wxThread( )
{
	m_pFrame      = m_frame;
	m_pRenderWin  = m_renderwin;
	m_pControlWin = m_controlwin;
}



void *MyRenderThread::Entry(void)
{
	if( TestDestroy() )
		return NULL;

	wxWindowDC m_dc( m_pRenderWin );
	RenderSpectrum(m_dc, true);

	return NULL;
}



void MyRenderThread::OnExit(void)
{
	wxCriticalSectionLocker locker(wxGetApp().m_critsect);

	wxArrayThread& threads = wxGetApp().m_threads;
	
	threads.Remove(this);
	
    if( threads.IsEmpty() )
    {
        if( wxGetApp().m_waitingUntilAllDone )
        {
            wxGetApp().m_waitingUntilAllDone = false;

            wxGetApp().m_semAllDone.Post();
        }
    }
	if( !m_pFrame->IsQuit && !m_pFrame->IsFinished )
	{
		m_pRenderWin->StartRenderThread();
	}
}



void MyRenderThread::RenderSpectrum(wxDC &dc, bool uselog)
{
	Sleep(25);

	int x, y;
	int r, g, b, ampli;
	float max, val, db;
	int   time   = FSOUND_Stream_GetTime(m_pRenderWin->m_pFrame->m_pStream);
	int   length = FSOUND_Stream_GetLengthMs(m_pRenderWin->m_pFrame->m_pStream);

	if( time == length || m_pRenderWin->m_pFrame->IsQuit )
	{
		m_pRenderWin->m_pFrame->IsFinished = true;
		m_pRenderWin->PaintInitialScreen( dc );
		return;
	}

	m_pRenderWin->GetClientSize(&x, &y);

	dc.SetDeviceOrigin(15, 0);

	wxBitmap bmp(x - 15, y - 12);

	wxMemoryDC memdc;
	memdc.SelectObject(bmp);	
	
	float *m_spectr = FSOUND_DSP_GetSpectrum();
 /*
    1.0   = 0db
    0.5   = -6db
    0.25  = -12db
    0.125 = -24db
 */
	max = 0.0f;
	for(int i = 0; i < x; i++)
	{
		if( x > 512 + ( i * 10 ) )
			x = 512 + (i * 10);
/*
		val = ( m_spectr[i]     +
				m_spectr[i+1]   +
				m_spectr[i+2]   +
				m_spectr[i+3]   +
				m_spectr[i+4]   +
				m_spectr[i+6]	+
				m_spectr[i+7]	+
				m_spectr[i+8]	+
				m_spectr[i+9]	) / 10;
*/
		val = m_spectr[i];

		if( val > max )
			max = val;

		if(uselog)
		{
			db = 10.0f * (float)log10(val) * 2.0f;

			val = db;
			if (val < -150)
			{
				val = -150;
			}
			val /= -150.0f;
			val = 1.0f - val;

			ampli = (int)( val * (float)ZONESPECTRE_HEIGHT );
		}
		else
		{
			ampli = (int)( val / max * (float)ZONESPECTRE_HEIGHT );
		}

		for(int j = ampli - 10; j < ampli; j++)
		{
				r = j << 1;
				g = 0xFF - (j << 1);
				b = 0x1F;

				if( r <= 0xFF && g <= 0xFF )
					memdc.SetPen( wxColour(r, g, b) );
				else memdc.SetPen( *wxRED );

#define AMPLITUDE(_x) (y - 12) - _x

				memdc.BeginDrawing();
				for(int l = i; l < i + 10; l++)
				{
					memdc.DrawPoint( l, AMPLITUDE( j ) );
				}
				memdc.EndDrawing();
		}
		i = i + 10;
	}
	memdc.SetPen(wxNullPen);
	dc.Blit( 0, 0, x, y, &memdc, 0, 0, wxCOPY );

	wxMemoryDC mmdc;
	wxBitmap mmbmp(120, 12);
	mmdc.SelectObject(mmbmp);
	mmdc.SetFont(*wxITALIC_FONT);
    mmdc.SetTextForeground( *wxLIGHT_GREY );

	wxString str;
	str.Printf("Thread 0x%lx DSP run", GetId());

	mmdc.DrawText(str, 1, 0);

	wxWindowDC Cdc(m_pControlWin);
	Cdc.Blit( 3, 126, 110, 12, &mmdc, 0, 0, wxCOPY );
}


BEGIN_EVENT_TABLE(PaneControl, wxFrame)
	EVT_PAINT(PaneControl::OnPaint)
END_EVENT_TABLE()

PaneControl::PaneControl(MyFrame *m_parent) : wxFrame (   NULL, 
														wxID_ANY, 
														wxEmptyString, 
														wxDefaultPosition, 
														wxSize(75, 160),
														wxCAPTION      |
														wxMINIMIZE_BOX |
														//wxSTAY_ON_TOP  |
														wxSYSTEM_MENU  | 
														wxFRAME_TOOL_WINDOW |
														wxNO_BORDER  ), m_pFrame(m_parent)
{
	SetBackgroundColour(*wxBLACK);
	SetTitle(_T("Levels"));

	int width, height, x, y;

	wxClientDisplayRect(&x, &y, &width, &height);

	wxPoint m_point(width - ZONESPECTRE_WIDTH - 130 - 75, height-160);
	SetPosition(m_point);

	Show( true );
}

PaneControl::~PaneControl()
{
}

void PaneControl::OnPaint(wxPaintEvent &WXUNUSED(event))
{
	wxPaintDC m_dc(this);
	m_dc.Clear();
	PaintInitialScreen(m_dc);
}

void PaneControl::PaintInitialScreen(wxDC &dc)
{
	dc.SetFont(wxFont(8, wxTELETYPE, wxNORMAL, wxNORMAL) );
    dc.SetTextForeground( *wxGREEN );

	dc.DrawText("LEVELS", 1, 1 );
}

MyLevelThread *PaneControl::CreateLevelThread( void )
{
	MyLevelThread *thread = new MyLevelThread(this, m_pFrame, m_pFrame->m_pControlWin);

    if ( thread->Create() != wxTHREAD_NO_ERROR )
    {
        wxLogError(_T("Can't create thread!"));
    }
	wxCriticalSectionLocker enter( wxGetApp().m_critsect );
	wxGetApp().m_threads.Add(thread);

    return thread;
}

void PaneControl::StartLevelThread( void )
{
	wxThread *thr = CreateLevelThread();

    if ( thr->Run() != wxTHREAD_NO_ERROR )
    {
        wxLogError(wxT("Can't start thread!"));
    }
	thr->SetPriority(WXTHREAD_DEFAULT_PRIORITY);	
}

BEGIN_EVENT_TABLE(ControlWin, wxFrame)
	EVT_PAINT(ControlWin::OnPaint)
END_EVENT_TABLE()



ControlWin::ControlWin(MyFrame *m_parent) : wxFrame (   NULL, 
														wxID_ANY, 
														wxEmptyString, 
														wxDefaultPosition, 
														wxSize(130, 200),
														wxCAPTION      |
														wxMINIMIZE_BOX |
														wxSYSTEM_MENU  | 
														wxFRAME_TOOL_WINDOW |
														wxNO_BORDER  ), m_pFrame(m_parent)
{
	int width, height, x, y;

	wxClientDisplayRect(&x, &y, &width, &height);

	wxPoint m_point(width - ZONESPECTRE_WIDTH - 130, height-200);
	SetPosition(m_point);
	SetTitle(_T("Controler"));
	SetBackgroundColour(*wxBLACK);
	Show( true );
}



ControlWin::~ControlWin()
{
}



void ControlWin::OnPaint(wxPaintEvent &WXUNUSED(event))
{
	wxPaintDC dc( this );
	PaintInitialScreen( dc );
}



void ControlWin::PaintInitialScreen(wxDC &dc)
{
	dc.SetFont(wxFont(8, wxTELETYPE, wxNORMAL, wxNORMAL) );
    dc.SetTextForeground( *wxGREEN );

	dc.DrawText("CONTROLER", 1, 1 );
}



MyControlThread *ControlWin::CreateControlThread(void)
{
	MyControlThread *thread = new MyControlThread(this, m_pFrame);

    if ( thread->Create() != wxTHREAD_NO_ERROR )
    {
        wxLogError(_T("Can't create thread!"));
    }
	wxCriticalSectionLocker enter( wxGetApp().m_critsect );
	wxGetApp().m_threads.Add(thread);

    return thread;
}



void ControlWin::StartControlThread(void)
{
	wxThread *thr = CreateControlThread();

    if ( thr->Run() != wxTHREAD_NO_ERROR )
    {
        wxLogError(wxT("Can't start thread!"));
    }
	thr->SetPriority(WXTHREAD_MIN_PRIORITY);	
}



BEGIN_EVENT_TABLE(DSPWnd, wxWindow)
	EVT_PAINT(DSPWnd::OnPaint)
	EVT_SIZE(DSPWnd::OnSize)
END_EVENT_TABLE()



DSPWnd::DSPWnd(MyFrame *m_parent) : wxWindow( m_parent, 
											  wxID_ANY, 
											  wxPoint(-1,-1),
											  wxSize(-1,-1), 
											  NULL,  
											  "" ), m_pFrame(m_parent)
{
	SetBackgroundColour(*wxBLACK);
	FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), true);

	if( !FSOUND_DSP_GetActive( FSOUND_DSP_GetFFTUnit() ) )
	{
		wxLogError("Can't active spctrum");
		return;
	}
}



DSPWnd::~DSPWnd()
{
}

void DSPWnd::PaintInitialScreen(wxDC &dc)
{
	int w, h, db, freq;
	wxString sDb, sFreq;

	GetClientSize(&w, &h);

	db = -24;
	freq = 0;

	dc.Clear();


	dc.SetPen(*wxWHITE);

	dc.SetFont( wxFont(5, wxSWISS, wxNORMAL, wxNORMAL) );
    dc.SetTextForeground( *wxWHITE );
	
	for(int i = 15; i < w; i++)
	{
		dc.DrawLine(i, h-2, i, h);
		i = i + 2;
	}
	for(int i = 5; i < h-10; i++)
	{
		dc.DrawLine(0, i, 2, i);
		i = i + 2;
	}
	for(int i = h; i > 0; i--)
	{
		i = i - 16;
		if(db <= 0)	
		{
			sDb.Printf("%d", db);
		}
		else 
		{
			sDb.Printf("+%d", db);
		}
		dc.DrawText( sDb, 3.2f, i );
		
		db = db + 4;
	}
	for(int i = 13; i < w; i++)
	{
		sFreq.Printf("%d", freq);

		dc.DrawText( sFreq, i, h-10 );

		freq = i * (float)43.06640625f;

		i = i + 23;
	}
}



void DSPWnd::OnPaint(wxPaintEvent &WXUNUSED(event))
{
	wxPaintDC dc(this);
	PaintInitialScreen( dc );
}



void DSPWnd::OnSize(wxSizeEvent &WXUNUSED(event))
{
    Refresh();
}



MyRenderThread *DSPWnd::CreateRenderThread()
{
	MyRenderThread *thread = new MyRenderThread(m_pFrame, this, m_pFrame->m_pControlWin);

    if ( thread->Create() != wxTHREAD_NO_ERROR )
    {
        wxLogError(_T("Can't create thread!"));
    }
	wxCriticalSectionLocker enter( wxGetApp().m_critsect );
	wxGetApp().m_threads.Add(thread);

    return thread;
}


void DSPWnd::StartRenderThread(void)
{
	wxThread *thr = CreateRenderThread();
	
	if ( thr->Run() != wxTHREAD_NO_ERROR )
	{
		wxLogError(wxT("Can't start thread!"));
	}
	size_t n = wxGetApp().m_threads.GetCount();

    if ( n == 0 )
          thr->SetPriority(WXTHREAD_MIN_PRIORITY);
    else if ( n == 1 )
          thr->SetPriority(WXTHREAD_MAX_PRIORITY);
    else
          thr->SetPriority(WXTHREAD_DEFAULT_PRIORITY);
}



IMPLEMENT_APP(MyApp)



BEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_CLOSE(MyFrame::OnClose)
	EVT_DROP_FILES(MyFrame::OnDrop)
END_EVENT_TABLE()


MyFrame::MyFrame() : wxFrame(   NULL, 
							    wxID_ANY, 
								_T("Spectrum"), 
								wxDefaultPosition, 
								wxDefaultSize, 
								wxCAPTION      |
								wxMINIMIZE_BOX |
								wxSYSTEM_MENU  | 
								wxCLOSE_BOX    |
								wxFRAME_TOOL_WINDOW	 )
{
	m_pStream  = NULL;
	data       = NULL;
	IsQuit     = false;
	IsFinished = false;
	channel    = 0;

	FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);

    if (FSOUND_GetVersion() < FMOD_VERSION)
    {
        wxLogError("Error : You are using the wrong DLL version!  You should be using FMOD %.02f\n", FMOD_VERSION);
        return;
    }

	if(!FSOUND_Init(44100, 32, NULL))
    {
        wxLogError("%s\n", FMOD_ErrorString(FSOUND_GetError()));
        return;
    }

	FSOUND_Stream_SetBufferSize(100);

	m_pControlWin = new ControlWin( this );

	m_pRenderWin = new DSPWnd( this );

	m_pPaneControl = new PaneControl( this );

	DragAcceptFiles( true );
}


MyFrame::~MyFrame(void)
{
	IsQuit = true;
	IsFinished = true;
    wxThread *thread;

    wxGetApp().m_critsect.Enter();

    const wxArrayThread& threads = wxGetApp().m_threads;
    size_t count = threads.GetCount();

    if ( count )
    {
        wxGetApp().m_waitingUntilAllDone = true;

        while ( ! threads.IsEmpty() )
        {
            thread = threads.Last();

            wxGetApp().m_critsect.Leave();

            thread->Delete();

            wxGetApp().m_critsect.Enter();
        }
    }

    wxGetApp().m_critsect.Leave();

    if ( count )
    {
        wxGetApp().m_semAllDone.Wait();
    }

	if( FSOUND_GetChannelsPlaying() > 0 )
		FSOUND_Stream_Close(m_pStream);

	FSOUND_Close();
	m_pControlWin->Destroy();
	m_pPaneControl->Destroy();

	if( data )
		delete [] data;
}

void MyFrame::OnClose(wxCloseEvent &WXUNUSED(event))
{
	Destroy();
}


void MyFrame::OnDrop(wxDropFilesEvent &event)
{
	IsFinished = true;
	wxThread::Sleep( 5 );

	wxString *arr;
	wxString strstream;

	arr = event.GetFiles();

	strstream = arr[0];

	PlayFile( strstream );
}



void MyFrame::PlayFile(const wxString &filename)
{
    int length;
	
	std::ifstream file;
	file.open(filename, std::ios::binary );
	file.seekg(0, std::ios::end);
	length = file.tellg();
	file.seekg(0, std::ios::beg);

	data = new char[length];

	file.read(data, length);

	file.close();

	if( FSOUND_GetChannelsPlaying() > 0 )
		FSOUND_Stream_Close(m_pStream);

	m_pStream = FSOUND_Stream_Open(data, FSOUND_NORMAL | FSOUND_MPEGACCURATE | FSOUND_LOADMEMORY, 0, length);

	channel = FSOUND_Stream_PlayEx(FSOUND_FREE, m_pStream, NULL, false);

	if(channel == -1)
	{
		wxLogError("Invalid Channel");
		return;
	}
	IsFinished = false;

	FSOUND_SetVolume(channel, 250);
	FSOUND_SetSurround(channel, true);

	if( wxGetApp().m_threads.IsEmpty() )
	{
		m_pRenderWin->StartRenderThread();
		m_pPaneControl->StartLevelThread();
		m_pControlWin->StartControlThread();
	}
}

 Conclusion

pour utiliser ce programme, glisser un fichier audio sur le fenetre du spectrum...

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

09 avril 2006 18:36:57 :
-- mise a l'echelle de fmod sur les frequences et améliorations sur db par rapport aux préamp mackie
09 avril 2006 21:50:40 :
-- vu que ce dev ne servira jamais a rien d'autre qu'a faire joli, ben j'ai amélioré le rendu en barres des 5 pixels 1 barre représente 93*5 hz a peu prés
10 avril 2006 18:16:09 :
-- modif du rendu car tout le monde n'a pas une super carte vidéo ( je m'inclus dedans lol )
11 avril 2006 02:26:06 :
-- derniere modif, a vous de jouer désormais....
11 avril 2006 03:26:45 :
--
11 avril 2006 16:37:21 :
-- ultimes modifications des threads
11 avril 2006 17:18:39 :
-- echelle des fréquences modifiée, fidéle a fmod mais je reste convaincu du contraire, mais bon, vu que c'est un exemple FMOD, alors on écoute FMOD :D
11 avril 2006 17:24:03 :
-¨¨-
13 avril 2006 18:47:19 :
--changement de la description, FMOD enregistre tt ce qui passe par la carte son !!!!

 Sources du même auteur

Source avec Zip [ FMODEX | WXWIDGETS ] CAPTURER L'OUTPUT AUDIO + ÉCRITURE DA...
Source avec Zip Source avec une capture WXWIDGETS -- > CLIENT FTP
Source avec Zip Source avec une capture ~~ PETIT LECTEUR VIDEO [ WXWIDGETS ----> WXMEDIACTRL ] ~~
Source avec Zip Source avec une capture --LECTEUR MP3/CD [WXWIDGETS+FMOD]--

 Sources de la même categorie

Source avec Zip Source avec une capture [WIN32] EASY WAVE MIXER par ordiman85
METTRE À JOUR LE TITRE DU MORCEAU EN COURS DANS MSN LIVE par citronz1969
Source avec Zip SUPER MINI MP3 JOUEUR par f_l_a_s_h_b_a_c_k
Source avec Zip MP3 RENAMER par dragonjoker59
Source avec Zip Source avec une capture LECTEUR DE MUSIQUE AVEC SDL ET FMOD par Lemng

 Sources en rapport avec celle ci

Source avec Zip CONVERTIR FLV 2 MP3 par nipepsinicolas
Source avec Zip Source avec une capture LECTEUR DE MUSIQUE AVEC SDL ET FMOD par Lemng
Source avec une capture JEU DE PENDU AVEC SDL, FMOD ET TTF par bad_dark_spirit
Source avec Zip Source avec une capture BOMBERMAN EN C++ ET SDL, MOTEUR TERMINÉ MAIS A AMÉLIORER, SA... par ionstorm356
Source avec Zip Source avec une capture ~~ PETIT LECTEUR VIDEO [ WXWIDGETS ----> WXMEDIACTRL ] ~~ par satellite34

Commentaires et avis

Commentaire de MuPuF le 09/04/2006 11:24:55

salut, l'input audio m'intérésse grandement car je voudrais faire une osciloscope de ma carte son (Oscilo pas cher) et meme pourquoi pas un générateur de fonction ?
Si quelqu'un commence ce projet je suis partant mais apres le bac lol

Commentaire de SAKingdom le 09/04/2006 14:58:37

Ey satellite34, ta enfin réussi. Bien. Comme tu vois, moi ça avance aussi. Attention, compétition en vue :) Il te reste comme moi à supporter les formats MP3 et autre.

Commentaire de MuPuF le 09/04/2006 15:36:02

je viens de faire un petit calcul, a 96 khz, on a une fréquence raffraichissement de 100 µs, c'est peu mais deja bien (celui de mon labo de SI est 500000* plus précis, il descend a 0.2ns :-S)

Commentaire de satellite34 le 09/04/2006 15:41:22

arf, non, j'ai rien réussi du tout ! ce n'est pas du tout ce que je voulais a la base mais bon, comme expliqué, posé ici pour exemple ultras débutants;

la, je le porte sous fmodEx, en c++, je ferais donc une mise a jour, avec des vrais calculs de db/freq, car la c'etait a taton, mais assez fidéle jusqu'a 22khz je pense.

de toute facoon, le gain absolu de fmod est de 0db, ce qui est absolument faux en réalité, donc obligé de tricher.

pour le rafraichissement, surment qu'une nette amélioration viendra, je suis en train d'opérer l'algo.

je vous tient au courant..

Commentaire de satellite34 le 09/04/2006 18:39:43

Mupuf -- si tu peux me dire comment faire les mesures que tu m'annonce ce serai bient cool ou sinon, faire un petite mesure la, car je pense que ca va bien plus vite, cause beaucoup moins de pixels car reéchelle, sinon, comment rescaler un dc?

Commentaire de satellite34 le 10/04/2006 00:44:20

SaKingdom -- > pourquoi mp3 et autres as- tu au moins testé le programme, il lit tous les fichiers audios et meme le son de certains avi + spectre bien sur

Commentaire de SAKingdom le 10/04/2006 02:09:01

Oui j'ai tester mais ya rien qui s'affiche. Je comprend pas comment ça marche.

Commentaire de satellite34 le 10/04/2006 02:10:19

description de la source, glisser un fichier audio sur la fenetre du spectre

Commentaire de SAKingdom le 10/04/2006 02:15:37

eh mais sa marche très bien ce programme. J'adore.

Commentaire de satellite34 le 10/04/2006 02:17:11

bof, suivant le pc, rapetissi le spectre car le rendu peu ralentir, sinon, ben ca me satisfait po. j'abandonne...
WaveOut passion.........

Commentaire de SAKingdom le 10/04/2006 02:24:18

Ah c'est pour ça cette question dans le forum. Tu veut plus de fmod? C'est pas toi qui voulais me convincre de l'utiliser? :P

Commentaire de satellite34 le 11/04/2006 03:31:16

voila, le programme a recu ses dernieres modifs, de meilleures perfs, mais aucun portage fmodEx ne sera opéré sur celui-ci;

voila, ben sinon, pour SA, FMOD est vraiment un super outil genre pour lecteur mp3 ou truk du genre, aprés je sais pas, je suis en train de voir qui a moyen d'enregistrer avec fmod donc affaire a suivre....

Commentaire de zakarita le 07/08/2007 14:14:48

slt!pourquoi quand on execute ce programme, il affiche que c'est impossible d'ouvrir le fichier en entrée wxmsw26d_core.lib?

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

FMOD ou Directx Audio [ par seb2086 ] Bonjour,Je voulait savoir qu'est ce qui &#233;tait le mieux entre FMOD et Directx Audio pour la gestion du son.Merci. tagsMp3+FMOD+wxWIDGETS [ par satellite34 ] salut, je voudrai r&#233;cuperer les tags des fichiers audio avec FMOD et wxWIDGETS .Pourriez vous me donner la m&#233;thode pour faire ca car je comp [wxWIDGETS] wxMediaCtrl + avi [ par satellite34 ] salut!petite question a 10 piastres:je veux lire un avis avec la librairie wxWIDGETS et sa fonction wxMediaCtrl.Quelqu' un pourrai - t-il me donner la A props de wxWidgets [ par lunnatick ] Bonjour quelqu'un saurait-il me dire comment utiliser " wxWidgets " ? mettre un wxImage en ressource ? -wxWidgets- [ par georgeduke ] Bonjour !! J'ai d&#233;velopp&#233; un petit programme avec devC++/wxWidgets qui affiche un fichier bmp pour embellir l'interface. J'aimerais savoir fmod j'ai besoin d'aide [ par unionx ] ---------------------------------------&gt;&lt;-------------------------------------------------salut tout le monde voila mo wxWIDGETS-->Une bonne librairie??.avis des développeurs : [ par satellite34 ] Bonjour,Je d&#233;veloppe depuis quelques temps avec la librairie wxWIDGETS car elle semble ultra portable et ergonomique--&gt;les mots cl&#233;s sont wxWIDGETS ----> mon aplli sous mac??? [ par satellite34 ] Bonjour,je d&#233;veloppe actuellement un client ftp avec wxDevCpp sous windows;Le truc, c'est que dans l' absolu ce programme est vou&#233; a tourner WxWidgets [ par boutonnet ] Bonjour a tous, je dois d&#233;velopper une application sous linux en utilisant les WxWidgets. Je me documente depuis deux jours sur ce GUI, mais une WXWIDGETS et linux [ par boutonnet ] Bonjour, je gal&#232;re a essayer de faire fonctionner les wxwidgets sur ma mandrake avec eclipse. autant dire que je n'y arrive pas, j'ai suivi a la


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,952 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales