Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

[ FMOD | WXWIDGETS]RENDU SPECTRUM -- MP3


Information sur la source

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 052 / 601

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

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

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

Pour les "Membres Club", vous pouvez 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 !!!!

Commentaires et avis

signaler à un administrateur
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

signaler à un administrateur
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.

signaler à un administrateur
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)

signaler à un administrateur
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..

signaler à un administrateur
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?

signaler à un administrateur
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

signaler à un administrateur
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.

signaler à un administrateur
Commentaire de satellite34 le 10/04/2006 02:10:19

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

signaler à un administrateur
Commentaire de SAKingdom le 10/04/2006 02:15:37

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

signaler à un administrateur
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.........

signaler à un administrateur
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

signaler à un administrateur
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....

signaler à un administrateur
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...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Comparez les prix Nouvelle version


HTC Magic

Entre 429€ et 429€


Photothèque Nouveau !



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
Temps d'éxécution de la page : 0,406 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.