585 lines
15 KiB
C++
585 lines
15 KiB
C++
#include "Precompiled.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "RakiEngine/Data/MemoryBlock/MemoryBlock.h"
|
|
#include "RakiEngine/Data/WaveFile/BinWaveData/BinWaveData.h"
|
|
#include "RakiEngine/Data/WaveFile/RiffChunkManager.h"
|
|
#include "RakiEngine/Sounds/PCMStreamSource.h"
|
|
#include "RakiEngine/Sounds/StreamBufferInfo.h"
|
|
#include "RakiEngine/Sounds/SoftwareEngine/StreamSoftwareSound.h"
|
|
#include "RakiEngine/Sources/SineSource.h"
|
|
#include "RakiEngine/Sources/Synth/MonophonicSynth.h"
|
|
#include "RakiTests/Sounds/PCMDataProvider.h"
|
|
|
|
#include "RakiEngine/Utils/Calcs.h"
|
|
|
|
#if defined ( RAKI_USING_XAUDIO2 )
|
|
|
|
#include "RakiEngine/Sounds/_XAudio2/PCMStreamSoundNative.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
#include <cell/mstream.h>
|
|
#include "RakiEngine/Sounds/_PS3/BufferSoundNative_PS3.h"
|
|
#include "RakiEngine/Sounds/_PS3/PCMStreamSoundNative_PS3.h"
|
|
#include "RakiTests/Sounds/MP3DataProvider.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII )
|
|
|
|
#include <revolution/vi.h>
|
|
|
|
#include "RakiEngine/Sounds/_Wii/BufferSoundNative_Wii.h"
|
|
#include "RakiEngine/Sounds/_Wii/PCMStreamSoundNative_Wii.h"
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
#include "RakiEngine/Sounds/_Cafe/PCMStreamSoundNative_Cafe.h"
|
|
|
|
#include "RakiTests/_Cafe/Memory/SimpleHeap_Cafe.h"
|
|
|
|
#endif
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
#include "RakiTests/_Win32/CoInitializeInitObject.h"
|
|
|
|
#endif // ( RAKI_PLATFORM_WIN32 )
|
|
|
|
|
|
|
|
#include "RakiTests/Initializer/TestInitializer.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace raki
|
|
{
|
|
|
|
|
|
|
|
enum NoteCommand
|
|
{
|
|
noteCommand_void,
|
|
noteCommand_playNote,
|
|
noteCommand_stopNote
|
|
};
|
|
|
|
|
|
NoteCommand getNoteCommand( const u32 _beatTwentyFourth, const u32 _rhythmType )
|
|
{
|
|
NoteCommand noteCommand = noteCommand_void;
|
|
|
|
switch ( _rhythmType )
|
|
{
|
|
case 0: // one note every beat
|
|
switch( _beatTwentyFourth )
|
|
{
|
|
case 0:
|
|
noteCommand = noteCommand_playNote;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 1: // one note every half beat
|
|
switch( _beatTwentyFourth )
|
|
{
|
|
case 0:
|
|
case 12:
|
|
noteCommand = noteCommand_playNote;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 2: // one note every third beat
|
|
switch( _beatTwentyFourth )
|
|
{
|
|
case 0:
|
|
case 8:
|
|
case 16:
|
|
noteCommand = noteCommand_playNote;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 3: // one note every quarter beat
|
|
switch( _beatTwentyFourth )
|
|
{
|
|
case 0:
|
|
case 6:
|
|
case 12:
|
|
case 18:
|
|
noteCommand = noteCommand_playNote;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
return noteCommand;
|
|
}
|
|
|
|
extern void SystemAllocator_Initialize();
|
|
|
|
#define STREAMINGSOURCE_NB_CHANNELS 2
|
|
|
|
// #define STREAMINGSOURCE_MAIN_THREAD_UPDATE_PERIOD_MILLISECONDS 6
|
|
// #define STREAMINGSOURCE_BUFFER_SAMPLESIZE ( STREAMINGSOURCE_MAIN_THREAD_UPDATE_PERIOD_MILLISECONDS * RAKI_NATIVE_SAMPLING_RATE / 800 ) // should be divided by 1000 for milliseconds - multiple by a bit more than 1.2 for safety
|
|
// #define STREAMINGSOURCE_BUFFER_ALIGNED_SAMPLESIZE ( ( STREAMINGSOURCE_BUFFER_SAMPLESIZE + 63 ) - ( ( STREAMINGSOURCE_BUFFER_SAMPLESIZE + 63 ) % 64 ) ) // should be divided by 1000 for milliseconds - multiple by a bit more than 1.2 for safety
|
|
// #define STREAMINGSOURCE_BUFFER_BYTESIZE ( STREAMINGSOURCE_BUFFER_ALIGNED_SAMPLESIZE * 2 * STREAMINGSOURCE_NB_CHANNELS )
|
|
|
|
#define STREAMINGSOURCE_BUFFER_BYTESIZE ( 512 * 2 * STREAMINGSOURCE_NB_CHANNELS )
|
|
|
|
bool m_isPlaying = false;
|
|
i32 m_midiNote = -1;
|
|
MonophonicSynth * m_synth = NULL;
|
|
|
|
void setSynthParams( const bool _playNote, const f32 x, const f32 y )
|
|
{
|
|
RAKI_ASSERT( x >= 0.f && x <= 1.f );
|
|
RAKI_ASSERT( y >= 0.f && y <= 1.f );
|
|
|
|
//const i32 scale[] = { 0, 2, 3, 5, 7, 8, 10 }; // F minor7
|
|
const i32 scale[] = { 0, 3, 5, 7, 10 }; // F penta minor
|
|
const i32 notesInScale = sizeof( scale ) / sizeof( i32 );
|
|
const i32 numScales = 3;
|
|
const i32 numNotes = numScales * notesInScale + 1;
|
|
|
|
if ( _playNote )
|
|
{
|
|
const i32 noteIndex = (i32)( ( 1.f - y ) * (f32)numNotes );
|
|
const i32 octave = noteIndex / notesInScale;
|
|
|
|
const i32 midiNote = MIDI_NOTE_F1 + 12 * octave + scale[ noteIndex % notesInScale ];
|
|
|
|
if ( midiNote != m_midiNote )
|
|
{
|
|
if ( m_midiNote >= 0 )
|
|
m_synth->stopNote( m_midiNote );
|
|
|
|
m_synth->startNote( midiNote );
|
|
|
|
m_midiNote = midiNote;
|
|
}
|
|
|
|
//m_synth->setDetune( 1.f + 0.001f * x );
|
|
}
|
|
else
|
|
{
|
|
if ( m_midiNote >= 0 )
|
|
m_synth->stopNote( m_midiNote );
|
|
|
|
m_midiNote = -1;
|
|
m_isPlaying = false;
|
|
}
|
|
|
|
//m_synth->setBehaviorVolume( -45.f * ( 1.f - x ) );
|
|
}
|
|
|
|
class AudioCallback : public raki::StreamBufferInfo::AudioCallbackStreamUpdateClient
|
|
{
|
|
public:
|
|
#if defined ( RAKI_USING_SOFTWARE_ENGINE )
|
|
AudioCallback( StreamSoftwareSound * _pcmStreamSound )
|
|
#else
|
|
AudioCallback( PCMStreamSoundNative * _pcmStreamSound )
|
|
#endif
|
|
: m_pcmStreamSound( _pcmStreamSound )
|
|
{
|
|
}
|
|
|
|
virtual void audioCallbackUpdateStreamPosition( const void * /*_clientData*/, const u64 /*_samplePosition*/ )
|
|
{
|
|
POINT point;
|
|
GetCursorPos( &point );
|
|
|
|
const int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
if ( point.x < 0 ) point.x = 0;
|
|
if ( point.x >= screenWidth ) point.x = screenWidth - 1;
|
|
|
|
const int screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
|
if ( point.y < 0 ) point.y = 0;
|
|
if ( point.y >= screenHeight ) point.y = screenHeight - 1;
|
|
|
|
const f32 frequency = 440.f * expf( 4.f * (f32) ( point.x - ( screenWidth / 2 ) ) / (f32) screenWidth );
|
|
|
|
//source.setFrequency( frequency );
|
|
|
|
const bool playing = GetAsyncKeyState( VK_LBUTTON );
|
|
//setSynthParams( playing, (f32) point.x / (f32) screenWidth, (f32) point.y / (f32) screenHeight );
|
|
|
|
static f32 m_beatInBar = 0.f;
|
|
m_beatInBar += 0.02f;
|
|
static u32 m_beatTwentyFourth = 0;
|
|
const u32 currentBeatTwentyFourth = ( (u32) ( 24.f * m_beatInBar ) ) % 24;
|
|
|
|
f32 m_x = (f32) point.x / (f32) screenWidth;
|
|
f32 m_y = (f32) point.y / (f32) screenHeight;
|
|
|
|
static f32 lastTime = 0.f;
|
|
f32 time = Time::getTime();
|
|
RAKI_OUTPUT( "currentBeatTwentyFourth %d (%.3f)", currentBeatTwentyFourth, time - lastTime );
|
|
lastTime = time;
|
|
|
|
if ( m_beatTwentyFourth != currentBeatTwentyFourth )
|
|
{
|
|
|
|
//RAKI_OUTPUT("0x%x PCMSourceInstance::audioCallbackUpdateStreamPosition currentBeatTwentyFourth %d", this, currentBeatTwentyFourth);
|
|
|
|
const i32 scale[] = { 0, 3, 5, 7, 10 }; // penta minor
|
|
const i32 notesInScale = sizeof( scale ) / sizeof( i32 );
|
|
const i32 numScales = 3;
|
|
const i32 numNotes = numScales * notesInScale + 1;
|
|
|
|
const i32 noteIndex = (i32)( ( 1.f - m_y ) * (f32)numNotes );
|
|
const i32 octave = noteIndex / notesInScale;
|
|
|
|
const i32 midiNote = MIDI_NOTE_C1 + 12 * octave + scale[ noteIndex % notesInScale ];
|
|
|
|
u32 rhythmType = 0;
|
|
if ( m_x < 0.2f )
|
|
rhythmType = 3; // one note every quarter beat
|
|
else if ( m_x < 0.4f )
|
|
rhythmType = 1; // one note every half beat
|
|
else if ( m_x < 0.6f )
|
|
rhythmType = 0; // one note every beat
|
|
else if ( m_x < 0.8f )
|
|
rhythmType = 1; // one note every half beat
|
|
else
|
|
rhythmType = 3; // one note every quarter beat
|
|
|
|
const NoteCommand noteComamnd = getNoteCommand( currentBeatTwentyFourth, rhythmType );
|
|
|
|
if ( noteComamnd == noteCommand_playNote )
|
|
{
|
|
if ( playing )
|
|
{
|
|
if ( m_midiNote >= 0 )
|
|
m_synth->stopNote( m_midiNote );
|
|
|
|
m_synth->startNote( midiNote );
|
|
|
|
m_midiNote = midiNote;
|
|
}
|
|
}
|
|
else if ( noteComamnd == noteCommand_stopNote )
|
|
{
|
|
m_synth->stopNote( m_midiNote );
|
|
|
|
m_midiNote = -1;
|
|
}
|
|
|
|
m_beatTwentyFourth = currentBeatTwentyFourth;
|
|
}
|
|
|
|
if ( !playing )
|
|
{
|
|
m_synth->stopNote( m_midiNote );
|
|
|
|
m_midiNote = -1;
|
|
}
|
|
|
|
|
|
m_pcmStreamSound->update();
|
|
}
|
|
|
|
private:
|
|
#if defined ( RAKI_USING_SOFTWARE_ENGINE )
|
|
StreamSoftwareSound * m_pcmStreamSound;
|
|
#else
|
|
PCMStreamSoundNative * m_pcmStreamSound;
|
|
#endif
|
|
|
|
};
|
|
|
|
void TestSourceStreaming();
|
|
void TestSourceStreaming()
|
|
{
|
|
bool buffersAllocated = false;
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
#if defined ( RAKI_USING_SOFTWARE_ENGINE )
|
|
StreamSoftwareSound pcmStreamSound;
|
|
#else
|
|
PCMStreamSoundNative pcmStreamSound;
|
|
#endif
|
|
|
|
// pcmStreamSound.getStreamBufferInfo()->setStreamUpdateClient( &testUpdateClient );
|
|
buffersAllocated = pcmStreamSound.allocateBuffers( STREAMINGSOURCE_BUFFER_BYTESIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
#elif defined ( RAKI_PLATFORM_XB360 )
|
|
|
|
PCMStreamSoundNative pcmStreamSound;
|
|
buffersAllocated = pcmStreamSound.allocateBuffers( STREAMINGSOURCE_BUFFER_BYTESIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
#elif defined ( RAKI_PLATFORM_WII ) || defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
PCMStreamSoundNative pcmStreamSound( STREAMINGSOURCE_NB_CHANNELS );
|
|
|
|
buffersAllocated = pcmStreamSound.allocateBuffers( STREAMINGSOURCE_BUFFER_BYTESIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
#elif defined ( RAKI_PLATFORM_PS3 )
|
|
|
|
PCMStreamSoundNative pcmStreamSound;
|
|
// mp3StreamSound.getStreamBufferInfo()->setStreamUpdateClient( &testUpdateClient );
|
|
buffersAllocated = pcmStreamSound.allocateBuffers( STREAMINGSOURCE_BUFFER_BYTESIZE );
|
|
RAKI_ASSERT( buffersAllocated );
|
|
|
|
#endif
|
|
|
|
const bool isMusic = false;
|
|
const bool isLooping = false;
|
|
SoundParams soundParams( isMusic, isLooping );
|
|
|
|
|
|
AudioCallback audioCallback( &pcmStreamSound );
|
|
pcmStreamSound.getStreamBufferInfo()->setAudioCallbackStreamUpdateClient( &audioCallback );
|
|
|
|
//SineSource source( STREAMINGSOURCE_NB_CHANNELS );
|
|
MonophonicSynth source;
|
|
m_synth = &source;
|
|
|
|
bool create = pcmStreamSound.createVoice( &source, soundParams );
|
|
RAKI_ASSERT( create );
|
|
|
|
pcmStreamSound.prepare( &source );
|
|
pcmStreamSound.updateRouting( true );
|
|
pcmStreamSound.start();
|
|
|
|
bool isPlaying = pcmStreamSound.isPlaying();
|
|
RAKI_ASSERT( isPlaying );
|
|
|
|
|
|
int count = 0;
|
|
bool playSynth = true;
|
|
|
|
for ( ;; )
|
|
{
|
|
bool isPlaying = false;
|
|
|
|
#ifdef RAKI_PLATFORM_WII
|
|
VIWaitForRetrace();
|
|
#else // RAKI_PLATFORM_WII
|
|
Thread::sleep( 25 );
|
|
#endif // RAKI_PLATFORM_WII
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_WIN32 )
|
|
/*
|
|
POINT point;
|
|
GetCursorPos( &point );
|
|
|
|
const int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
if ( point.x < 0 ) point.x = 0;
|
|
if ( point.x >= screenWidth ) point.x = screenWidth - 1;
|
|
|
|
const int screenHeight = GetSystemMetrics(SM_CYSCREEN);
|
|
if ( point.y < 0 ) point.y = 0;
|
|
if ( point.y >= screenHeight ) point.y = screenHeight - 1;
|
|
|
|
const f32 frequency = 440.f * expf( 4.f * (f32) ( point.x - ( screenWidth / 2 ) ) / (f32) screenWidth );
|
|
|
|
//source.setFrequency( frequency );
|
|
|
|
const bool playing = GetAsyncKeyState( VK_LBUTTON );
|
|
if ( playSynth )
|
|
setSynthParams( playing, (f32) point.x / (f32) screenWidth, (f32) point.y / (f32) screenHeight );
|
|
*/
|
|
//pcmStreamSound.update();
|
|
isPlaying |= pcmStreamSound.isPlaying();
|
|
|
|
#else
|
|
|
|
//pcmStreamSound.update();
|
|
isPlaying |= pcmStreamSound.isPlaying();
|
|
|
|
#endif
|
|
|
|
// if ( !isPlaying )
|
|
// break;
|
|
|
|
|
|
++count;
|
|
/*
|
|
if ( count == 100 )
|
|
{
|
|
RAKI_OUTPUT("stop");
|
|
pcmStreamSound.stop();
|
|
playSynth = false;
|
|
}
|
|
|
|
if ( count == 200 )
|
|
{
|
|
RAKI_OUTPUT("start");
|
|
pcmStreamSound.start();
|
|
pcmStreamSound.update();
|
|
playSynth = true;
|
|
|
|
count = 0;
|
|
}
|
|
*/
|
|
}
|
|
|
|
pcmStreamSound.stop();
|
|
|
|
// XAudio2 doc: Stop is always asynchronous, even if called within a callback
|
|
Thread::sleep( 5000 );
|
|
|
|
pcmStreamSound.destroyVoice();
|
|
|
|
Thread::sleep( 500 );
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace raki
|
|
|
|
|
|
|
|
#if defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
|
|
u32 running_core;
|
|
u32 main_core;
|
|
u32 first_subcore;
|
|
u32 second_subcore;
|
|
u32 wait_main_core;
|
|
u32 wait_first_subcore;
|
|
u32 wait_second_subcore;
|
|
OSRendezvous rendezvous;
|
|
|
|
void
|
|
SetupCoreIds(void)
|
|
{
|
|
running_core = OSGetCoreId();
|
|
main_core = OSGetMainCoreId();
|
|
|
|
first_subcore = 0;
|
|
second_subcore = 2;
|
|
wait_main_core = OS_WAIT_CORE_MAIN;
|
|
wait_first_subcore = OS_WAIT_CORE_SUB1;
|
|
wait_second_subcore = OS_WAIT_CORE_SUB2;
|
|
|
|
if (main_core == 0)
|
|
{
|
|
first_subcore = 1;
|
|
second_subcore = 2;
|
|
wait_main_core = OS_WAIT_CORE_SUB1;
|
|
wait_first_subcore = OS_WAIT_CORE_MAIN;
|
|
wait_second_subcore = OS_WAIT_CORE_SUB2;
|
|
}
|
|
else
|
|
if (main_core == 2)
|
|
{
|
|
first_subcore = 0;
|
|
second_subcore = 1;
|
|
wait_main_core = OS_WAIT_CORE_SUB2;
|
|
wait_first_subcore = OS_WAIT_CORE_SUB1;
|
|
wait_second_subcore = OS_WAIT_CORE_MAIN;
|
|
}
|
|
}
|
|
|
|
int run_demo (int intArg, void *ptrArg)
|
|
{
|
|
raki::SimpleHeap_Cafe::init();
|
|
|
|
raki::TestInitializer initializer;
|
|
|
|
raki::TestSourceStreaming();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined ( RAKI_USING_XAUDIO2 )
|
|
int _tmain( int /*argc*/, _TCHAR* /*argv[]*/ )
|
|
#else // RAKI_USING_XAUDIO2
|
|
int main( int /*argc*/, char * /*argv[]*/ )
|
|
#endif // RAKI_USING_XAUDIO2
|
|
{
|
|
#if defined ( RAKI_PLATFORM_WII )
|
|
DVDInit();
|
|
VIInit();
|
|
|
|
raki::SystemAllocator_Initialize();
|
|
|
|
#elif defined ( RAKI_PLATFORM_WIN32 )
|
|
|
|
raki::CoInitializeInitObject coInitializeInitObject;
|
|
|
|
#elif defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
u32 gx2InitAttribs[] =
|
|
{
|
|
GX2_INIT_ATTRIB_NULL // terminates the list
|
|
};
|
|
GX2Init(gx2InitAttribs);
|
|
|
|
// launch test on Core 0 if present
|
|
if (OSGetCoreCount() == 3)
|
|
{
|
|
OSThread* defaultThread0;
|
|
|
|
SetupCoreIds();
|
|
|
|
OSReport("Running Core == %d\n", running_core);
|
|
OSReport("OS Main Core == %d\n\n", main_core);
|
|
|
|
OSInitRendezvous(&rendezvous);
|
|
|
|
//
|
|
// Restart default thread on 1st subcore, core0
|
|
//
|
|
|
|
defaultThread0 = OSGetDefaultThread(first_subcore);
|
|
OSRunThread(defaultThread0,
|
|
run_demo,
|
|
0,
|
|
(void*) 0x23232323);
|
|
|
|
OSWaitRendezvous(&rendezvous, wait_first_subcore);
|
|
}
|
|
else
|
|
{
|
|
run_demo(0, NULL);
|
|
}
|
|
|
|
GX2Shutdown();
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
|
|
#if !defined ( RAKI_PLATFORM_CAFE )
|
|
|
|
raki::TestInitializer initializer;
|
|
|
|
raki::TestSourceStreaming();
|
|
|
|
return 0;
|
|
|
|
#endif // !defined ( RAKI_PLATFORM_CAFE )
|
|
}
|
|
|
|
|
|
|
|
|