begin process at 2012 02 08 21:10:35
  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é :8 287 / 690

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 ADAPTER LES TEMPS DE SUBTITLES DE SOUS TITRAGE ENTRE DEUX LA... par berrami
Source avec Zip Source avec une capture DÉTECTION DE VISAGE (YEUX, NEZ, BOUCHE) AVEC OPENCV EN TEMPS... par MadM@tt
Source avec Zip Source avec une capture GÉNÉRATEUR FM EXPÉRIMENTAL par tontonCD
Source avec Zip LECTEUR MULTIMÉDIA par omegatou
Source avec Zip IMPLÉMENTATION D'UN ALGORITHME DE COMPRESSION/DECOMPRESSION ... par eemikhm

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture BEAT DETECTION par barsichou
WXFREECHART PIEPLOT EXAMPLE par neria
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 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 Problème pour lire les fichiers audio dans un programme C++ [ par Nicolas ] Pour un projet C++ (linéaire),il souhaiterais réalisé une bibliothèque musical(.mp3, .wav). J'aurais besoin pour ca de lire les fichiers audio mais je Poblèmes pour lire un fichier audio dans un programme C++ [ par Nicolas ] Pour un projet C++ (linéaire),il souhaiterais réalisé une bibliothèque musical(.mp3, .wav). J'aurais besoin pour ca de lire les fichiers audio mais je utiliser les codecs (audio) en VC++ [ par MangaII ] Salut !Je cherche a utiliser les codecs pour décompresser des son, mais j'ai pas encore réussi !Si qqun c comment on pe faire ca, sans trop se compliq Récupération des données audio sous DirectX [ par kleinjer ] Bonjour,Je débute avec DirectX. J'ai une interface qui me permet d'ouvrir un fichier wav ou mp3 mais j'aurais besoin de recupérer les données audio af initialisation de Fmod avec devC++ [ par cppdupdup34 ] je n'y arrive pas je crois qu' il faut faire quelque chose dans lezs option du projet mais je ne sait pas quoi.si vous avez une minute!!mercicppDupDup controle du volume audio général [ par roxanic ] BonjourJe cherche a controler les bouton de volume.Pour le bouton Wave c'est OK. Mais je ne trouve pas le solution pour le curseur du volume général.M enregistrer un msg audio (cross-plateforme) [ par gaune ] Salut a tous,je travaille actuellement sur un site, un projet avec des enfants, et je souhaiterais pouvoir enregistrer des messages audio. Et bien sur


Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

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 : 7,394 sec (3)

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