|
From: <pst...@us...> - 2008-04-05 23:43:44
|
Revision: 399
http://jazzplusplus.svn.sourceforge.net/jazzplusplus/?rev=399&view=rev
Author: pstieber
Date: 2008-04-05 16:43:43 -0700 (Sat, 05 Apr 2008)
Log Message:
-----------
1. Changes JZPlayer::samples to mSamples.
2. Made several stylistic changes in the Windows audio interface code.
3. Started making similar changes to the Linux version.
4. Made cosmetic changes.
Modified Paths:
--------------
trunk/jazz/src/AlsaDriver.cpp
trunk/jazz/src/AlsaDriver.h
trunk/jazz/src/AudioDriver.cpp
trunk/jazz/src/AudioDriver.h
trunk/jazz/src/Player.cpp
trunk/jazz/src/Player.h
trunk/jazz/src/mswin/WindowsAudioInterface.cpp
trunk/jazz/src/mswin/WindowsAudioInterface.h
Modified: trunk/jazz/src/AlsaDriver.cpp
===================================================================
--- trunk/jazz/src/AlsaDriver.cpp 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/AlsaDriver.cpp 2008-04-05 23:43:43 UTC (rev 399)
@@ -45,89 +45,100 @@
using namespace std;
-#define snd_pcm_write(pcm,data,size) snd_pcm_writei(pcm,data,size)
-#define snd_pcm_read(pcm,data,size) snd_pcm_readi(pcm,data,size)
-
#define MAX_FRAGS 16 // enough large?
-
-
class tAlsaAudioListener : public wxTimer
{
public:
- tAlsaAudioListener(tAlsaAudioPlayer *p, int key)
+
+ tAlsaAudioListener(tAlsaAudioPlayer* pPlayer, int key)
+ : wxTimer(),
+ mpPlayer(pPlayer),
{
- hard_exit = TRUE;
- player = p;
- player->listener = this;
- player->rec_info = 0; // not recording!
- player->running_mode = 0;
-
+ mHardExit = TRUE;
+ mpPlayer->mpListener = this;
+ mpPlayer->rec_info = 0; // not recording!
+ mpPlayer->running_mode = 0;
+
// SYNC seems not to work?? so add 8 more silent buffers
// to hear the end of the sample too.
- player->OpenDsp(tAlsaAudioPlayer::PLAYBACK, 0);
- count = 8 + player->samples.PrepareListen(key);
+ mpPlayer->OpenDsp(tAlsaAudioPlayer::PLAYBACK, 0);
+ mCount = 8 + mpPlayer->mSamples.PrepareListen(key);
Start(20);
}
- tAlsaAudioListener(tAlsaAudioPlayer *p, tSample &spl, long fr_smpl, long to_smpl)
+ tAlsaAudioListener(
+ tAlsaAudioPlayer* pPlayer,
+ tSample& spl,
+ long fr_smpl,
+ long to_smpl)
+ : wxTimer(),
+ mpPlayer(pPlayer),
{
- hard_exit = TRUE;
- player = p;
- player->listener = this;
- player->rec_info = 0; // not recording!
- player->running_mode = 0;
+ mHardExit = TRUE;
+ mpPlayer->mpListener = this;
+ mpPlayer->rec_info = 0; // not recording!
+ mpPlayer->running_mode = 0;
- player->OpenDsp(tAlsaAudioPlayer::PLAYBACK, 0);
- player->samples.ResetBufferSize(player->frag_byte_size[tAlsaAudioPlayer::PLAYBACK]);
- count = 8 + player->samples.PrepareListen(&spl, fr_smpl, to_smpl);
+ mpPlayer->OpenDsp(tAlsaAudioPlayer::PLAYBACK, 0);
+
+ mpPlayer->mSamples.ResetBufferSize(
+ mpPlayer->frag_byte_size[tAlsaAudioPlayer::PLAYBACK]);
+
+ mCount = 8 + mpPlayer->mSamples.PrepareListen(&spl, fr_smpl, to_smpl);
+
Start(20);
}
~tAlsaAudioListener()
{
Stop();
- player->CloseDsp(hard_exit);
- player->listener = 0;
+ mpPlayer->CloseDsp(mHardExit);
+ mpPlayer->mpListener = 0;
}
virtual void Notify()
{
- count -= player->WriteSamples();
- count += player->samples.ContinueListen();
- if (count <= 0)
+ mCount -= mpPlayer->WriteSamples();
+ mCount += mpPlayer->mSamples.ContinueListen();
+ if (mCount <= 0)
{
- hard_exit = FALSE;
+ mHardExit = FALSE;
delete this;
}
}
long GetPlayPosition()
{
- return player->GetCurrentPosition(tAlsaAudioPlayer::PLAYBACK);
+ return mpPlayer->GetCurrentPosition(tAlsaAudioPlayer::PLAYBACK);
}
private:
- tAlsaAudioPlayer *player;
- int count;
- int hard_exit;
+
+ tAlsaAudioPlayer* mpPlayer;
+
+ int mCount;
+
+ int mHardExit;
};
-tAlsaAudioPlayer::tAlsaAudioPlayer(JZSong *song)
- : tAlsaPlayer(song)
+tAlsaAudioPlayer::tAlsaAudioPlayer(JZSong* pSong)
+ : tAlsaPlayer(pSong)
{
AudioBuffer = new tEventArray();
installed = 0;
audio_enabled = 0;
- listener = 0;
- can_duplex = 0; // no duplex yet.
+ mpListener = 0;
+ mCanDuplex = 0; // no duplex yet.
pcm[PLAYBACK] = NULL;
pcm[CAPTURE] = NULL;
dev[PLAYBACK] = gpConfig->StrValue(C_AlsaAudioOutputDevice);
dev[CAPTURE] = gpConfig->StrValue(C_AlsaAudioInputDevice);
- can_duplex = 1; /* FIXME */
+
+ // FIXME
+ mCanDuplex = 1;
installed = 1;
audio_enabled = 1;
}
@@ -135,7 +146,7 @@
tAlsaAudioPlayer::~tAlsaAudioPlayer()
{
- delete listener;
+ delete mpListener;
delete AudioBuffer;
if (pcm[PLAYBACK])
{
@@ -152,7 +163,7 @@
int tAlsaAudioPlayer::LoadSamples(const char *filename)
{
- return samples.Load(filename);
+ return mSamples.Load(filename);
}
int tAlsaAudioPlayer::RecordMode() const
@@ -167,8 +178,8 @@
void tAlsaAudioPlayer::StartPlay(long clock, long loopClock, int cont)
{
- delete listener;
- samples.StartPlay(clock);
+ delete mpListener;
+ mSamples.StartPlay(clock);
tAlsaPlayer::StartPlay(clock, loopClock, cont);
if (!audio_enabled)
@@ -177,7 +188,7 @@
}
long ticks_per_minute = Song->TicksPerQuarter * Song->Speed();
- samples.ResetBuffers(AudioBuffer, clock, ticks_per_minute);
+ mSamples.ResetBuffers(AudioBuffer, clock, ticks_per_minute);
last_scount = 0;
cur_pos = 0;
audio_clock_offset = clock;
@@ -191,11 +202,11 @@
recbuffers.ResetBufferSize(frag_byte_size[CAPTURE]);
}
- if (dev[CAPTURE] != dev[PLAYBACK] || can_duplex || running_mode == 0)
+ if (dev[CAPTURE] != dev[PLAYBACK] || mCanDuplex || running_mode == 0)
{
OpenDsp(PLAYBACK, 1);
- samples.ResetBufferSize(frag_byte_size[PLAYBACK]);
- samples.FillBuffers(OutClock);
+ mSamples.ResetBufferSize(frag_byte_size[PLAYBACK]);
+ mSamples.FillBuffers(OutClock);
}
if (running_mode == 0)
@@ -216,31 +227,42 @@
void tAlsaAudioPlayer::StartAudio()
{
if (pcm[PLAYBACK])
+ {
snd_pcm_start(pcm[PLAYBACK]);
+ }
if (pcm[CAPTURE])
+ {
snd_pcm_start(pcm[CAPTURE]);
+ }
}
void tAlsaAudioPlayer::OpenDsp(int mode, int sync_mode)
{
if (!audio_enabled)
+ {
return;
+ }
unsigned int channels;
snd_pcm_format_t format;
snd_pcm_uframes_t buffer_size, period_size;
frame_shift[mode] = 0;
- if (samples.BitsPerSample() == 8)
+ if (mSamples.BitsPerSample() == 8)
+ {
format = SND_PCM_FORMAT_U8;
- else {
+ }
+ else
+ {
format = SND_PCM_FORMAT_S16_LE;
frame_shift[mode]++;
}
- channels = samples.GetChannels();
+ channels = mSamples.GetChannels();
if (channels > 1)
+ {
frame_shift[mode]++;
+ }
snd_pcm_stream_t stream = (mode == PLAYBACK) ?
SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE;
@@ -269,20 +291,22 @@
perror("cannot set audio channels");
goto __error;
}
- if (snd_pcm_hw_params_set_rate(pcm[mode], hw, samples.GetSpeed(), 0) < 0)
+ if (snd_pcm_hw_params_set_rate(pcm[mode], hw, mSamples.GetSpeed(), 0) < 0)
{
- cerr << "cannot set audio rate: " << samples.GetSpeed() << endl;
+ cerr << "cannot set audio rate: " << mSamples.GetSpeed() << endl;
goto __error;
}
period_size = FRAGBYTES >> frame_shift[mode];
- if ((period_size = snd_pcm_hw_params_set_period_size_near(pcm[mode], hw, &period_size, 0)) < 0)
+ if (
+ (period_size = snd_pcm_hw_params_set_period_size_near(pcm[mode], hw, &period_size, 0)) < 0)
{
perror("cannot set audio period");
goto __error;
}
buffer_size = period_size * MAX_FRAGS;
- if ((buffer_size = snd_pcm_hw_params_set_buffer_size_near(pcm[mode], hw, &buffer_size)) < 0)
+ if (
+ (buffer_size = snd_pcm_hw_params_set_buffer_size_near(pcm[mode], hw, &buffer_size)) < 0)
{
perror("cannot set audio buffer");
goto __error;
@@ -302,9 +326,14 @@
snd_pcm_sw_params_alloca(&sw);
snd_pcm_sw_params_current(pcm[mode], sw);
if (sync_mode)
- snd_pcm_sw_params_set_start_threshold(pcm[mode], sw, 0x7fffffff); /* FIXME */
+ {
+ // FIXME
+ snd_pcm_sw_params_set_start_threshold(pcm[mode], sw, 0x7fffffff);
+ }
else
+ {
snd_pcm_sw_params_set_start_threshold(pcm[mode], sw, 1);
+ }
if (snd_pcm_sw_params(pcm[mode], sw) < 0)
{
perror("snd_pcm_sw_params");
@@ -323,41 +352,47 @@
}
-void tAlsaAudioPlayer::CloseDsp(int reset)
+void tAlsaAudioPlayer::CloseDsp(bool Reset)
{
if (pcm)
{
- if (reset)
+ if (Reset)
{
if (pcm[PLAYBACK])
{
if (snd_pcm_drop(pcm[PLAYBACK]) < 0)
+ {
perror("playback drop");
+ }
}
}
else
{
if (pcm[PLAYBACK])
{
- if (snd_pcm_drain(pcm[PLAYBACK]) < 0 )
+ if (snd_pcm_drain(pcm[PLAYBACK]) < 0)
+ {
perror("playback drain");
+ }
}
if (pcm[CAPTURE])
{
- if (snd_pcm_drain(pcm[CAPTURE]) < 0 )
+ if (snd_pcm_drain(pcm[CAPTURE]) < 0)
+ {
perror("capture drain");
+ }
}
}
if (pcm[PLAYBACK])
{
snd_pcm_close(pcm[PLAYBACK]);
pcm[PLAYBACK] = NULL;
- }
+ }
if (pcm[CAPTURE])
{
snd_pcm_close(pcm[CAPTURE]);
pcm[CAPTURE] = NULL;
- }
+ }
}
}
@@ -368,15 +403,22 @@
if (pcm[PLAYBACK])
{
WriteSamples();
- // here it may hang when swapping in pages
- samples.FillBuffers(OutClock);
+
+ // The code may hang here when swapping in pages.
+ mSamples.FillBuffers(OutClock);
+
WriteSamples();
}
+
if (pcm[CAPTURE])
+ {
ReadSamples();
+ }
- if (pcm[PLAYBACK] && samples.softsync)
+ if (pcm[PLAYBACK] && mSamples.softsync)
+ {
MidiSync();
+ }
}
tAlsaPlayer::Notify();
}
@@ -398,7 +440,9 @@
int tAlsaAudioPlayer::WriteSamples()
{
if (!audio_enabled || pcm[PLAYBACK] == NULL)
+ {
return 0;
+ }
int blocks_written = 0;
int room;
@@ -407,11 +451,19 @@
for (; room > frag_size[PLAYBACK]; room -= frag_size[PLAYBACK])
{
- tAudioBuffer *buf = samples.full_buffers.Get();
+ tAudioBuffer *buf = mSamples.full_buffers.Get();
if (buf == 0)
+ {
break;
- ssize_t written = snd_pcm_writei(pcm[PLAYBACK], buf->Data(), frag_size[PLAYBACK]);
- if (written < 0) {
+ }
+
+ ssize_t written = snd_pcm_writei(
+ pcm[PLAYBACK],
+ buf->Data(),
+ frag_size[PLAYBACK]);
+
+ if (written < 0)
+ {
if (written == -EPIPE)
{
cerr << "xrun!!" << endl;
@@ -423,9 +475,11 @@
}
}
if (written > 0)
+ {
cur_scount += written;
+ }
blocks_written++;
- samples.free_buffers.Put(buf);
+ mSamples.free_buffers.Put(buf);
}
return blocks_written;
@@ -435,14 +489,16 @@
void tAlsaAudioPlayer::ReadSamples()
{
if (!audio_enabled || pcm[CAPTURE] == NULL)
+ {
return;
+ }
int room = GetFreeSpace(CAPTURE);
for (; room > frag_size[CAPTURE]; room -= frag_size[CAPTURE])
{
short *b = recbuffers.RequestBuffer()->data;
- if (snd_pcm_read(pcm[CAPTURE], b, frag_size[CAPTURE]) !=
+ if (snd_pcm_readi(pcm[CAPTURE], b, frag_size[CAPTURE]) !=
frag_size[CAPTURE])
{
recbuffers.UndoRequest();
@@ -459,7 +515,7 @@
{
snd_pcm_drop(pcm[PLAYBACK]);
//long ticks_per_minute = Song->TicksPerQuarter * Song->Speed();
- //samples.ResetBuffers(AudioBuffer, clock, ticks_per_minute);
+ //mSamples.ResetBuffers(AudioBuffer, clock, ticks_per_minute);
}
audio_clock_offset = clock;
cur_pos = 0;
@@ -473,15 +529,23 @@
void tAlsaAudioPlayer::MidiSync()
{
if (!audio_enabled)
+ {
return;
+ }
int mode;
if (pcm[PLAYBACK])
+ {
mode = PLAYBACK;
+ }
else if (pcm[CAPTURE])
+ {
mode = CAPTURE;
+ }
else
+ {
return; // disabled
+ }
long scount = GetCurrentPosition(mode);
@@ -499,12 +563,17 @@
qtick = snd_seq_queue_status_get_tick_time(status);
int samplediff;
if (scount < last_scount)
+ {
samplediff = frame_boundary[mode] - (last_scount - scount);
+ }
else
+ {
samplediff = scount - last_scount;
+ }
last_scount = scount;
cur_pos += samplediff;
- long audio_clock = (long)samples.Samples2Ticks(cur_pos) + audio_clock_offset;
+ long audio_clock =
+ (long)mSamples.Samples2Ticks(cur_pos) + audio_clock_offset;
int delta_clock = audio_clock - qtick;
int new_speed = midi_speed + delta_clock;
@@ -527,26 +596,24 @@
snd_seq_ev_set_subs(&ev);
snd_seq_ev_set_direct(&ev);
snd_seq_ev_set_fixed(&ev);
- int us = (int)( 60.0E6 / (double)new_speed );
+ int us = (int)(60.0E6 / new_speed);
snd_seq_ev_set_queue_tempo(&ev, queue, us);
write(&ev, 1);
curr_speed = new_speed;
- // xview has reentrancy problems!!
- // gpTrackWindow->DrawSpeed(curr_speed);
}
}
}
void tAlsaAudioPlayer::StopPlay()
{
- samples.StopPlay();
+ mSamples.StopPlay();
tAlsaPlayer::StopPlay();
if (!audio_enabled)
{
return;
}
- CloseDsp(TRUE);
+ CloseDsp(true);
if (RecordMode())
{
long frc = rec_info->mFromClock;
@@ -559,53 +626,67 @@
{
toc = recd_clock;
}
- samples.SaveRecordingDlg(frc, toc, recbuffers);
+ mSamples.SaveRecordingDlg(frc, toc, recbuffers);
}
recbuffers.Clear();
- // xview has reentrancy problems!!
- // gpTrackWindow->DrawSpeed(midi_speed);
}
void tAlsaAudioPlayer::ListenAudio(int key, int start_stop_mode)
{
if (!audio_enabled)
+ {
return;
+ }
- // when already listening then stop listening
- if (listener)
+ // If already listening then stop listening.
+ if (mpListener)
{
- delete listener;
- listener = 0;
+ delete mpListener;
+ mpListener = 0;
if (start_stop_mode)
+ {
return;
+ }
}
if (key < 0)
+ {
return;
+ }
if (pcm[PLAYBACK]) // device busy (playing)
+ {
return;
- listener = new tAlsaAudioListener(this, key);
+ }
+
+ mpListener = new tAlsaAudioListener(this, key);
}
-void tAlsaAudioPlayer::ListenAudio(tSample &spl, long fr_smpl, long to_smpl)
+void tAlsaAudioPlayer::ListenAudio(tSample& spl, long fr_smpl, long to_smpl)
{
if (!audio_enabled)
+ {
return;
+ }
- // when already listening then stop listening
- if (listener)
+ // If already listening then stop listening.
+ if (mpListener)
{
- delete listener;
- listener = 0;
+ delete mpListener;
+ mpListener = 0;
}
+
if (pcm[PLAYBACK]) // device busy (playing)
+ {
return;
- listener = new tAlsaAudioListener(this, spl, fr_smpl, to_smpl);
+ }
+ mpListener = new tAlsaAudioListener(this, spl, fr_smpl, to_smpl);
}
long tAlsaAudioPlayer::GetListenerPlayPosition()
{
- if (!listener)
+ if (!mpListener)
+ {
return -1L;
- return listener->GetPlayPosition();
+ }
+ return mpListener->GetPlayPosition();
}
Modified: trunk/jazz/src/AlsaDriver.h
===================================================================
--- trunk/jazz/src/AlsaDriver.h 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/AlsaDriver.h 2008-04-05 23:43:43 UTC (rev 399)
@@ -48,31 +48,39 @@
virtual void SetAudioEnabled(int x) { audio_enabled = x; }
virtual void ListenAudio(int key, int start_stop_mode = 1);
virtual void ListenAudio(tSample &spl, long fr_smpl, long to_smpl);
- virtual bool IsListening() const {
- return listener != 0;
+ virtual bool IsListening() const
+ {
+ return mpListener != 0;
}
virtual long GetListenerPlayPosition();
virtual void StartAudio();
virtual void ResetPlay(long clock);
- enum { PLAYBACK = 0, CAPTURE };
+ enum
+ {
+ PLAYBACK = 0,
+ CAPTURE
+ };
// for recording
int RecordMode() const;
int PlayBackMode() const;
private:
- int can_duplex; // TRUE = can do full duplex record/play
int WriteSamples();
void ReadSamples();
void MidiSync();
void OpenDsp(int mode, int sync_mode);
- void CloseDsp(int reset);
+ void CloseDsp(bool Reset);
+
long GetCurrentPosition(int mode);
int GetFreeSpace(int mode);
+ // If true can do full duplex record/play.
+ int mCanDuplex;
+
snd_pcm_t *pcm[2];
int installed;
@@ -92,7 +100,7 @@
int frame_shift[2];
long frame_boundary[2];
- tAlsaAudioListener *listener;
+ tAlsaAudioListener* mpListener;
tAudioRecordBuffer recbuffers;
};
Modified: trunk/jazz/src/AudioDriver.cpp
===================================================================
--- trunk/jazz/src/AudioDriver.cpp 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/AudioDriver.cpp 2008-04-05 23:43:43 UTC (rev 399)
@@ -34,63 +34,83 @@
#include <fcntl.h>
-
#define AUDIO_DEVICE "/dev/dsp"
class tAudioListener : public wxTimer
{
public:
- tAudioListener(tAudioPlayer *p, int key) {
- hard_exit = TRUE;
- player = p;
- player->listener = this;
- player->rec_info = 0; // not recording!
+ tAudioListener(tAudioPlayer* pPlayer, int key)
+ : wxTimer(),
+ mpPlayer(pPlayer),
+ mCount(0),
+ mHardExit(true)
+ {
+ mpPlayer->mpListener = this;
+
+ mpPlayer->rec_info = 0; // not recording!
+
// SYNC seems not to work?? so add 8 more silent buffers
// to hear the end of the sample too.
- count = 8 + player->samples.PrepareListen(key);
- player->OpenDsp();
+ mCount = 8 + mpPlayer->samples.PrepareListen(key);
+ mpPlayer->OpenDsp();
Start(20);
}
- tAudioListener(tAudioPlayer *p, tSample &spl, long fr_smpl, long to_smpl) {
- hard_exit = TRUE;
- player = p;
- player->listener = this;
- player->rec_info = 0; // not recording!
+ tAudioListener(
+ tAudioPlayer* pPlayer,
+ tSample& spl,
+ long fr_smpl,
+ long to_smpl)
+ : wxTimer(),
+ mpPlayer(pPlayer),
+ mCount(0),
+ mHardExit(true),
+ {
+ mpPlayer = p;
+ mpPlayer->mpListener = this;
+ mpPlayer->rec_info = 0; // not recording!
- count = 8 + player->samples.PrepareListen(&spl, fr_smpl, to_smpl);
- player->OpenDsp();
+ mCount = 8 + mpPlayer->samples.PrepareListen(&spl, fr_smpl, to_smpl);
+ mpPlayer->OpenDsp();
Start(20);
}
- ~tAudioListener() {
+ ~tAudioListener()
+ {
Stop();
- player->CloseDsp(hard_exit);
- player->listener = 0;
+ mpPlayer->CloseDsp(mHardExit);
+ mpPlayer->mpListener = 0;
}
- virtual void Notify() {
- count -= player->WriteSamples();
- count += player->samples.ContinueListen();
- if (count <= 0)
+ virtual void Notify()
+ {
+ mCount -= mpPlayer->WriteSamples();
+ mCount += mpPlayer->samples.ContinueListen();
+ if (mCount <= 0)
{
- hard_exit = FALSE;
+ mHardExit = false;
delete this;
}
}
- long GetPlayPosition() {
+ long GetPlayPosition()
+ {
count_info cinfo;
- if (ioctl(player->dev, SNDCTL_DSP_GETOPTR, &cinfo) == -1)
+ if (ioctl(mpPlayer->dev, SNDCTL_DSP_GETOPTR, &cinfo) == -1)
+ {
perror("SNDCTL_DSP_GETOPTR");
+ }
return (cinfo.bytes - cinfo.ptr) / sizeof(short);
}
private:
- tAudioPlayer *player;
- int count;
- int hard_exit;
+
+ tAudioPlayer* mpPlayer;
+
+ int mCount;
+
+ int mHardExit;
};
@@ -99,41 +119,55 @@
: tSeq2Player(song)
{
long dummy = 0;
- AudioBuffer = new tEventArray();
- installed = 0;
+ AudioBuffer = new tEventArray();
+ installed = 0;
dummy = gpConfig->GetValue(C_EnableAudio);
audio_enabled = dummy;
- listener = 0;
- can_duplex = 0; // no duplex yet.
- dev = -1;
+ mpListener = 0;
+ mCanDuplex = 0; // no duplex yet.
+ dev = -1;
// check for device
dev = open(AUDIO_DEVICE, O_WRONLY, 0);
- if (dev >= 0) {
+ if (dev >= 0)
+ {
// check device caps
int caps;
ioctl(dev, SNDCTL_DSP_GETCAPS, &caps);
if (caps & DSP_CAP_REALTIME)
+ {
; // fprintf(stderr, AUDIO " supports REALTIME, good!\n");
+ }
+
if (caps & DSP_CAP_DUPLEX)
- can_duplex = 1; // good soundcard!
+ {
+ mCanDuplex = 1; // good soundcard!
+ }
+
if (!(caps & DSP_CAP_TRIGGER))
- fprintf(stderr, "no CAP_TRIGGER support!\n");
+ {
+ cerr << "no CAP_TRIGGER support!" << endl;
+ }
else
+ {
installed = 1;
+ }
+
close(dev);
}
else
+ {
perror(AUDIO_DEVICE);
+ }
+
dev = -1; // closed
audio_enabled = audio_enabled && installed;
-
}
tAudioPlayer::~tAudioPlayer()
{
- delete listener;
+ delete mpListener;
delete AudioBuffer;
if (dev >= 0)
close(dev);
@@ -153,12 +187,16 @@
void tAudioPlayer::StartAudio()
{
if (!audio_enabled)
+ {
return;
+ }
long ticks_per_minute = Song->TicksPerQuarter * Song->Speed();
samples.ResetBuffers(AudioBuffer, start_clock, ticks_per_minute);
if (PlaybackMode())
+ {
samples.FillBuffers(OutClock);
+ }
audio_bytes = 0;
midi_clock = 0;
@@ -191,9 +229,11 @@
int tmp;
if (!audio_enabled)
+ {
return;
+ }
- can_duplex = gpConfig->GetValue(C_DuplexAudio);
+ mCanDuplex = gpConfig->GetValue(C_DuplexAudio);
// linux driver seems to need some real free memory, which sometimes
// is not available when operating with big samples. So allocate
@@ -207,61 +247,91 @@
}
int mode = 0;
- if (can_duplex)
+ if (mCanDuplex)
+ {
mode = O_RDWR;
+ }
else if (RecordMode())
+ {
mode = O_RDONLY;
+ }
else
+ {
mode = O_WRONLY;
+ }
dev = open(AUDIO_DEVICE, mode, 0);
- if (dev < 0) {
+ if (dev < 0)
+ {
perror(AUDIO_DEVICE);
audio_enabled = 0;
return;
}
- if (can_duplex)
+ if (mCanDuplex)
+ {
ioctl(dev, SNDCTL_DSP_SETDUPLEX, 0);
+ }
tmp = 0xffff0000 | FRAGBITS;
- if (ioctl(dev, SNDCTL_DSP_SETFRAGMENT, &tmp)==-1)
+ if (ioctl(dev, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
+ {
perror("ioctl DSP_SETFRAGMENT");
+ }
tmp = samples.BitsPerSample();
ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp);
if (tmp != samples.BitsPerSample())
- fprintf(stderr, "Unable to set the sample size\n");
+ {
+ cerr << "Unable to set the sample size" << endl;
+ }
tmp = (samples.GetChannels() == 1) ? 0 : 1;
- if (ioctl (dev, SNDCTL_DSP_STEREO, &tmp)==-1)
- fprintf (stderr, "Unable to set mono/stereo\n");
+ if (ioctl (dev, SNDCTL_DSP_STEREO, &tmp) == -1)
+ {
+ cerr << "Unable to set mono/stereo" << endl;
+ }
tmp = samples.GetSpeed();
if (ioctl (dev, SNDCTL_DSP_SPEED, &tmp) == -1)
+ {
perror("ioctl DSP_SPEED");
+ }
- // check if fragsize was ok
- ioctl (dev, SNDCTL_DSP_GETBLKSIZE, &tmp);
+ // Check to see if the fragment size was OK.
+ ioctl(dev, SNDCTL_DSP_GETBLKSIZE, &tmp);
if (tmp < 1)
- perror ("GETBLKSIZE");
+ {
+ perror("GETBLKSIZE");
+ }
else if (tmp != FRAGBYTES)
- fprintf(stderr, "Unable to verify FRAGMENT %d, fbytes = %d, fshorts = %d\n", tmp, FRAGBYTES, FRAGSHORTS);
+ {
+ cerr
+ << "Unable to verify FRAGMENT " << tmp
+ << ", fbytes = " << FRAGBYTES
+ << ", fshorts = " << FRAGSHORTS
+ << endl;
+ }
}
-void tAudioPlayer::CloseDsp(int reset)
+void tAudioPlayer::CloseDsp(bool Reset)
{
if (dev >= 0)
{
- if (reset)
+ if (Reset)
{
if (ioctl(dev, SNDCTL_DSP_RESET, 0) == -1)
+ {
perror("SNDCTL_DSP_RESET");
+ }
}
- else {
+ else
+ {
if (ioctl (dev, SNDCTL_DSP_SYNC, NULL) < 0)
+ {
perror("SNDCTL_DSP_SYNC");
+ }
}
close(dev);
dev = -1;
@@ -271,18 +341,26 @@
void tAudioPlayer::Notify()
{
- if (audio_enabled) {
- if (PlaybackMode()) {
+ if (audio_enabled)
+ {
+ if (PlaybackMode())
+ {
WriteSamples();
+
// here it may hang when swapping in pages
samples.FillBuffers(OutClock);
+
WriteSamples();
}
if (RecordMode())
+ {
ReadSamples();
+ }
if (samples.softsync)
+ {
MidiSync();
+ }
}
tSeq2Player::Notify();
}
@@ -291,25 +369,34 @@
int tAudioPlayer::WriteSamples()
{
if (!audio_enabled)
+ {
return 0;
+ }
int blocks_written = 0;
// number of blocks to be written
audio_buf_info info;
if (ioctl(dev, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
perror("SNDCTL_DSP_GETOSPACE");
+ }
// todo: this is a bug in the audiodriver in newer kernels (2.1.28)
// and the oss/linux for 2.0.29 it should be
- // for (int i = 0; i < info.fragments; i++) {
+ // for (int i = 0; i < info.fragments; i++)
- for (int i = 0; i < info.fragments - 1; i++) {
+ for (int i = 0; i < info.fragments - 1; i++)
+ {
tAudioBuffer *buf = samples.full_buffers.Get();
if (buf == 0)
+ {
break;
+ }
if (write(dev, buf->Data(), BUFBYTES) != BUFBYTES)
+ {
perror("write");
+ }
blocks_written ++;
samples.free_buffers.Put(buf);
}
@@ -322,21 +409,29 @@
{
audio_buf_info info;
if (ioctl(dev, SNDCTL_DSP_GETISPACE, &info) == -1)
+ {
perror("SNDCTL_DSP_GETISPACE");
+ }
// a oss bug: if read is not called, there will be
// no recording. probably recording does NOT start
// exactly in sync with midi - but who knows.
if (force_read && !info.fragments)
+ {
info.fragments = 1;
+ }
force_read = 0;
- for (int i = 0; i < info.fragments; i++) {
+ for (int i = 0; i < info.fragments; i++)
+ {
short *b = recbuffers.RequestBuffer()->data;
- if (read(dev, b, BUFBYTES) != BUFBYTES) {
+ if (read(dev, b, BUFBYTES) != BUFBYTES)
+ {
// oss bug? It send EINTR?? on first read..
if (errno != EINTR && errno != EAGAIN)
+ {
perror("read");
+ }
recbuffers.UndoRequest();
break;
}
@@ -347,21 +442,27 @@
void tAudioPlayer::MidiSync()
{
- // OSS is buggy! In Win32 SDK you read the docs, hack away and
- // everything works. In OSS, there are no docs and if it works
+ // OSS is buggy! In Win32 SDK you read the docs, hack away and
+ // everything works. In OSS, there are no docs and if it works
// with kernel x it wont with kernel y.
if (!audio_enabled)
+ {
return;
+ }
int command = SNDCTL_DSP_GETOPTR;
if (!PlaybackMode())
+ {
command = SNDCTL_DSP_GETIPTR;
+ }
// get realtime info for audio/midi sync
count_info cinfo;
if (ioctl(dev, command, &cinfo) == -1)
+ {
perror("SNDCTL_DSP_GETOPTR");
+ }
// search for SNDCTL_DSP_GETOPTR in linux/drivers/sound/dmabuf
// before trying to understand the next line
@@ -370,12 +471,16 @@
{
// driver has processed some bytes or whole fragment
if (ioctl(seqfd, SNDCTL_SEQ_GETTIME, &midi_clock) < 0)
- perror("ioctl SNDCTL_SEQ_GETTIME failed - please get a newer kernel (2.1.28 or up)");
+ {
+ perror(
+ "ioctl SNDCTL_SEQ_GETTIME failed - "
+ "please get a newer kernel (2.1.28 or up)");
+ }
audio_bytes = new_bytes;
// OSS bug?: mpu401 does not like speed changes too often
- long audio_clock = (long)samples.Samples2Ticks(audio_bytes/2);
- int delta_clock = audio_clock - midi_clock;
+ long audio_clock = (long)samples.Samples2Ticks(audio_bytes / 2);
+ int delta_clock = audio_clock - midi_clock;
int new_speed = midi_speed + delta_clock;
// limit speed changes to some reasonable values
@@ -392,20 +497,21 @@
if (new_speed != curr_speed)
{
if (ioctl(seqfd, SNDCTL_TMR_TEMPO, &new_speed) < 0)
- // this sometimes happens with mpu-401 timer
+ {
+ // Sometimes this happens with mpu-401 timer.
; // perror("SNDCTL_TMR_TEMPO");
+ }
else
+ {
curr_speed = new_speed;
- // xview has reentrancy problems!!
- // gpTrackWindow->DrawSpeed(curr_speed);
+ }
}
-
}
}
void tAudioPlayer::StartPlay(long Clock, long LoopClock, int Continue)
{
- delete listener;
+ delete mpListener;
samples.StartPlay(Clock);
tSeq2Player::StartPlay(Clock, LoopClock, Continue);
}
@@ -415,21 +521,26 @@
samples.StopPlay();
tSeq2Player::StopPlay();
if (!audio_enabled)
+ {
return;
- CloseDsp(TRUE);
+ }
+
+ CloseDsp(true);
if (RecordMode())
{
long frc = rec_info->mFromClock;
if (frc < start_clock)
+ {
frc = start_clock;
+ }
long toc = rec_info->mToClock;
if (toc > recd_clock)
+ {
toc = recd_clock;
+ }
samples.SaveRecordingDlg(frc, toc, recbuffers);
}
recbuffers.Clear();
- // xview has reentrancy problems!!
- // gpTrackWindow->DrawSpeed(midi_speed);
}
@@ -437,42 +548,58 @@
void tAudioPlayer::ListenAudio(int key, int start_stop_mode)
{
if (!audio_enabled)
+ {
return;
+ }
// when already listening then stop listening
- if (listener)
+ if (mpListener)
{
- delete listener;
- listener = 0;
+ delete mpListener;
+ mpListener = 0;
if (start_stop_mode)
+ {
return;
+ }
}
if (key < 0)
+ {
return;
+ }
if (dev >= 0) // device busy (playing)
+ {
return;
- listener = new tAudioListener(this, key);
+ }
+
+ mpListener = new tAudioListener(this, key);
}
void tAudioPlayer::ListenAudio(tSample &spl, long fr_smpl, long to_smpl)
{
if (!audio_enabled)
+ {
return;
+ }
// when already listening then stop listening
- if (listener)
- delete listener;
+ if (mpListener)
+ {
+ delete mpListener;
+ }
+
if (dev >= 0) // device busy (playing)
+ {
return;
- listener = new tAudioListener(this, spl, fr_smpl, to_smpl);
+ }
+ mpListener = new tAudioListener(this, spl, fr_smpl, to_smpl);
}
-long tAudioPlayer::GetListenerPlayPosition() {
- if (!listener)
+long tAudioPlayer::GetListenerPlayPosition()
+{
+ if (!mpListener)
+ {
return -1L;
- return listener->GetPlayPosition();
+ }
+ return mpListener->GetPlayPosition();
}
-
-
-
Modified: trunk/jazz/src/AudioDriver.h
===================================================================
--- trunk/jazz/src/AudioDriver.h 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/AudioDriver.h 2008-04-05 23:43:43 UTC (rev 399)
@@ -27,7 +27,7 @@
// in oss/free (from kernel 2.0.29) the following is not implemented
// but this works for oss/linux for 2.0.29
// #ifndef SNDCTL_SEQ_GETTIME
-// #define SNDCTL_SEQ_GETTIME _IOR ('Q',19, int)
+// #define SNDCTL_SEQ_GETTIME _IOR ('Q',19, int)
// #endif
#include <sys/time.h>
@@ -43,52 +43,83 @@
class tAudioPlayer : public tSeq2Player
{
friend class tAudioListener;
+
public:
+
tAudioPlayer(JZSong *song);
+
virtual ~tAudioPlayer();
+
int LoadSamples(const char *filename);
+
virtual void Notify();
+
virtual void StartPlay(long Clock, long LoopClock = 0, int Continue = 0);
+
virtual void StopPlay();
+
virtual void StartAudio();
- virtual int Installed() { return installed && tSeq2Player::Installed(); }
- virtual int GetAudioEnabled() const { return audio_enabled; }
- virtual void SetAudioEnabled(int x) { audio_enabled = x; }
+
+ virtual int Installed()
+ {
+ return installed && tSeq2Player::Installed();
+ }
+
+ virtual int GetAudioEnabled() const
+ {
+ return audio_enabled;
+ }
+
+ virtual void SetAudioEnabled(int x)
+ {
+ audio_enabled = x;
+ }
+
virtual void ListenAudio(int key, int start_stop_mode = 1);
+
virtual void ListenAudio(tSample &spl, long fr_smpl, long to_smpl);
- virtual bool IsListening() const {
- return listener != 0;
+
+ virtual bool IsListening() const
+ {
+ return mpListener != 0;
}
+
virtual long GetListenerPlayPosition();
// for recording
int RecordMode() const;
- int PlaybackMode() const {
- return !RecordMode() || can_duplex;
+
+ int PlaybackMode() const
+ {
+ return !RecordMode() || mCanDuplex;
}
private:
- int can_duplex; // TRUE = can do full duplex record/play
+ // If true can do full duplex record/play.
+ int mCanDuplex;
+
int WriteSamples();
void ReadSamples();
void MidiSync();
void OpenDsp();
- void CloseDsp(int reset);
+ void CloseDsp(bool Reset);
+
int dev;
int installed;
long midi_clock;
long audio_bytes;
- int midi_speed; // start speed in bpm
- int curr_speed; // actual speed in bpm
- int audio_enabled; // 0 means midi only
+ int midi_speed; // start speed in bpm
+ int curr_speed; // actual speed in bpm
+ int audio_enabled; // 0 means midi only
- tAudioListener *listener;
+ tAudioListener* mpListener;
tAudioRecordBuffer recbuffers;
- int force_read; // needed by buggy audio driver ...
+ // Needed by buggy audio driver ...
+ int force_read;
};
#endif // !define(JZ_AUDIODRIVER_H)
Modified: trunk/jazz/src/Player.cpp
===================================================================
--- trunk/jazz/src/Player.cpp 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/Player.cpp 2008-04-05 23:43:43 UTC (rev 399)
@@ -191,7 +191,7 @@
JZPlayer::JZPlayer(JZSong *song)
- : samples( song->TicksPerQuarter * song->Speed() )
+ : mSamples(song->TicksPerQuarter * song->Speed())
{
DummyDeviceList.Add("default");
poll_millisec = 200; // default
Modified: trunk/jazz/src/Player.h
===================================================================
--- trunk/jazz/src/Player.h 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/Player.h 2008-04-05 23:43:43 UTC (rev 399)
@@ -36,7 +36,9 @@
#include <sys/types.h>
#include <time.h>
+class JZRecordingInfo;
+
// audio-menu
#define MEN_AUDIO_LOAD 200
#define MEN_AUDIO_SAVE 201
@@ -65,7 +67,7 @@
long Int2ExtClock(long Clock);
void PrepareOutput(
- tEventArray *buf,
+ tEventArray* buf,
JZSong* pSong,
long ExtFr,
long ExtTo,
@@ -74,14 +76,18 @@
private:
long mStartClock;
+
long mStopClock;
};
-enum tClockSource { CsInt = 0, CsFsk, CsMidi, CsMtc };
+enum tClockSource
+{
+ CsInt = 0,
+ CsFsk,
+ CsMidi,
+ CsMtc
+};
-class JZRecordingInfo;
-
-
class tDeviceList
{
public:
@@ -197,22 +203,29 @@
virtual void ListenAudio(tSample &spl, long fr_smpl, long to_smpl) {}
virtual bool IsListening() const { return 0; }
- virtual int OnMenuCommand(int id) {
+ virtual int OnMenuCommand(int id)
+ {
if (Playing)
{
return 0;
}
- return samples.OnMenuCommand(id);
+ return mSamples.OnMenuCommand(id);
}
- virtual const char *GetSampleName(int i) {
- return samples.GetSampleName(i);
+
+ virtual const char *GetSampleName(int i)
+ {
+ return mSamples.GetSampleName(i);
}
- virtual void AdjustAudioLength(JZTrack *t) {
+
+ virtual void AdjustAudioLength(JZTrack *t)
+ {
long ticks_per_minute = Song->TicksPerQuarter * Song->Speed();
- samples.AdjustAudioLength(t, ticks_per_minute);
+ mSamples.AdjustAudioLength(t, ticks_per_minute);
}
- void EditSample(int key) {
- samples.Edit(key);
+
+ void EditSample(int key)
+ {
+ mSamples.Edit(key);
}
virtual long GetListenerPlayPosition()
@@ -222,14 +235,17 @@
void LoadDefaultSettings()
{
- samples.LoadDefaultSettings();
+ mSamples.LoadDefaultSettings();
}
protected:
- tSampleSet samples;
+ tSampleSet mSamples;
+
public:
+
JZPlayer(JZSong *song);
+
virtual ~JZPlayer();
void Notify();
Modified: trunk/jazz/src/mswin/WindowsAudioInterface.cpp
===================================================================
--- trunk/jazz/src/mswin/WindowsAudioInterface.cpp 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/mswin/WindowsAudioInterface.cpp 2008-04-05 23:43:43 UTC (rev 399)
@@ -42,63 +42,83 @@
#define LeaveCriticalSection(a)
#define DeleteCriticalSection(a)
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
class tAudioListener : public wxTimer
{
// play a sample from piano roll
public:
- tAudioListener(tWinAudioPlayer *p, int key)
+ tAudioListener(tWinAudioPlayer* pPlayer, int key)
+ : wxTimer(),
+ mpPlayer(pPlayer),
+ mCount(0),
+ mHardExit(true),
+ mChannels(0)
{
- hard_exit = TRUE;
- player = p;
- player->listener = this;
- player->rec_info = 0; // not recording!
- channels = player->samples.GetChannels();
+ mpPlayer->mpListener = this;
- count = player->samples.PrepareListen(key);
- player->OpenDsp();
- player->StartAudio();
+ // Indicate that we are not recording!
+ mpPlayer->rec_info = 0;
+
+ mChannels = mpPlayer->mSamples.GetChannels();
+
+ mCount = mpPlayer->mSamples.PrepareListen(key);
+
+ mpPlayer->OpenDsp();
+
+ mpPlayer->StartAudio();
+
Start(200);
}
tAudioListener(
- tWinAudioPlayer *p,
- tSample &spl,
+ tWinAudioPlayer* pPlayer,
+ tSample& spl,
long fr_smpl,
long to_smpl)
+ : wxTimer(),
+ mpPlayer(pPlayer),
+ mCount(0),
+ mHardExit(true),
+ mChannels(0)
{
- hard_exit = TRUE;
- player = p;
- player->listener = this;
- player->rec_info = 0; // not recording!
- channels = player->samples.GetChannels();
+ mpPlayer->mpListener = this;
- count = player->samples.PrepareListen(&spl, fr_smpl, to_smpl);
- player->OpenDsp();
- player->StartAudio();
+ // Indicate that we are not recording!
+ mpPlayer->rec_info = 0;
+
+ mChannels = mpPlayer->mSamples.GetChannels();
+
+ mCount = mpPlayer->mSamples.PrepareListen(&spl, fr_smpl, to_smpl);
+
+ mpPlayer->OpenDsp();
+
+ mpPlayer->StartAudio();
+
Start(200);
}
~tAudioListener()
{
Stop();
- // todo: if !hard_exit flush outstanding buffers to device
+
+ // todo: if !mHardExit flush outstanding buffers to device
// before closing
- player->CloseDsp();
- player->listener = 0;
+ mpPlayer->CloseDsp();
+ mpPlayer->mpListener = 0;
}
virtual void Notify()
{
- EnterCriticalSection(&player->mutex);
- count += player->samples.ContinueListen();
- player->WriteBuffers();
- LeaveCriticalSection(&player->mutex);
- if (player->blocks_played >= count)
+ EnterCriticalSection(&mpPlayer->mutex);
+ mCount += mpPlayer->mSamples.ContinueListen();
+ mpPlayer->WriteBuffers();
+ LeaveCriticalSection(&mpPlayer->mutex);
+ if (mpPlayer->blocks_played >= mCount)
{
- hard_exit = FALSE;
+ mHardExit = false;
delete this;
}
}
@@ -107,21 +127,29 @@
{
MMTIME mmtime;
mmtime.wType = TIME_SAMPLES;
- waveOutGetPosition(player->hout, &mmtime, sizeof(mmtime));
- return mmtime.u.sample * channels;
+ waveOutGetPosition(mpPlayer->hout, &mmtime, sizeof(mmtime));
+ return mmtime.u.sample * mChannels;
}
private:
- tWinAudioPlayer *player;
- long count;
- int hard_exit;
- long channels;
-};
+ tWinAudioPlayer* mpPlayer;
+ long mCount;
-tWinAudioPlayer::tWinAudioPlayer(JZSong *song)
- : tWinIntPlayer(song)
+ bool mHardExit;
+
+ long mChannels;
+};
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+tWinAudioPlayer::tWinAudioPlayer(JZSong* pSong)
+ : tWinIntPlayer(pSong),
+ mErrorCode(NoError),
+ mCanDuplex(false),
+ mCanSynchronize(true),
+ mpListener(0)
{
state->audio_player = this;
@@ -132,15 +160,12 @@
installed = 0;
dummy = gpConfig->GetValue(C_EnableAudio);
audio_enabled = dummy;
- listener = 0;
hout_open = 0;
hinp_open = 0;
// check for device
installed = 0;
- can_duplex = (gpConfig->GetValue(C_DuplexAudio) != 0);
- error = NoError;
- can_sync = 1;
+ mCanDuplex = (gpConfig->GetValue(C_DuplexAudio) != 0);
if (OpenDsp() == 0)
{
@@ -149,99 +174,109 @@
MMRESULT res = waveOutGetDevCaps((UINT)hout, &ocaps, sizeof(ocaps));
if (res != MMSYSERR_NOERROR)
{
- error = ErrCapGet;
+ mErrorCode = ErrCapGet;
}
else if (!(ocaps.dwSupport & WAVECAPS_SAMPLEACCURATE))
{
- // not a real error
- wxMessageBox("your soundcard does not support audio/midi sync", "Warning", wxOK);
- can_sync = 0;
+ // This is not an error; just a warning.
+ wxMessageBox(
+ "Your soundcard does not support audio/midi sync",
+ "Warning",
+ wxOK);
+ mCanSynchronize = false;
}
- if (!error && CloseDsp() == 0)
+ if (!mErrorCode && CloseDsp() == 0)
+ {
installed = 1;
+ }
}
recbuffers.Clear();
audio_enabled = (audio_enabled && installed);
-
}
-
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
tWinAudioPlayer::~tWinAudioPlayer()
{
- delete listener;
+ delete mpListener;
delete AudioBuffer;
- // close device if open
+
+ // Close the device if it is open.
CloseDsp();
- // release semaphor
+
+ // Release the semaphor.
DeleteCriticalSection(&mutex);
}
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::ShowError()
{
- const char *msg = 0;
- switch (error)
+ const char* pMessage = 0;
+ switch (mErrorCode)
{
case ErrOutOpen:
- msg = "Cannot open audio output device";
+ pMessage = "Cannot open audio output device";
break;
case ErrOutPrepare:
- msg = "Cannot prepare audio output headers";
+ pMessage = "Cannot prepare audio output headers";
break;
case ErrOutUnprepare:
- msg = "Cannot unprepare audio output headers";
+ pMessage = "Cannot unprepare audio output headers";
break;
case ErrInpOpen:
- msg = "Cannot open audio input device";
+ pMessage = "Cannot open audio input device";
break;
case ErrInpPrepare:
- msg = "Cannot prepare audio input headers";
+ pMessage = "Cannot prepare audio input headers";
break;
case ErrInpUnprepare:
- msg = "Cannot unprepare audio input headers";
+ pMessage = "Cannot unprepare audio input headers";
break;
case ErrCapGet:
- msg = "Unable to get audio device capbabilities";
+ pMessage = "Unable to get audio device capbabilities";
break;
case ErrCapSync:
- msg = "Your soundcard does not support audio/midi sync";
+ pMessage = "Your soundcard does not support audio/midi sync";
break;
}
- if (msg)
- wxMessageBox((char *)msg, "Error", wxOK);
+ if (pMessage)
+ {
+ wxMessageBox(pMessage, "Error", wxOK);
+ }
}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
int tWinAudioPlayer::LoadSamples(const char *filename)
{
- return samples.Load(filename);
+ return mSamples.Load(filename);
}
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
int tWinAudioPlayer::OpenDsp()
{
int i;
MMRESULT res;
- error = NoError; // everything ok for now.
+ mErrorCode = NoError; // everything ok for now.
if (!audio_enabled)
{
return 0;
}
- can_duplex = (gpConfig->GetValue(C_DuplexAudio) != 0);
+ mCanDuplex = (gpConfig->GetValue(C_DuplexAudio) != 0);
// specify the data format
WAVEFORMATEX fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.wFormatTag = WAVE_FORMAT_PCM;
- fmt.nChannels = samples.GetChannels();
- fmt.nSamplesPerSec = samples.GetSpeed();
- fmt.nBlockAlign = samples.GetChannels() * sizeof(short);
+ fmt.nChannels = mSamples.GetChannels();
+ fmt.nSamplesPerSec = mSamples.GetSpeed();
+ fmt.nBlockAlign = mSamples.GetChannels() * sizeof(short);
fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
fmt.wBitsPerSample = 16;
fmt.cbSize = 0;
@@ -264,14 +299,14 @@
if (res != MMSYSERR_NOERROR)
{
- error = ErrOutOpen;
+ mErrorCode = ErrOutOpen;
return 1;
}
// prepare headers
for (i = 0; i < BUFCOUNT; i++)
{
- tAudioBuffer *buf = samples.GetBuffer(i);
+ tAudioBuffer *buf = mSamples.GetBuffer(i);
WAVEHDR *hdr = new WAVEHDR;
memset(hdr, 0, sizeof(WAVEHDR));
buf->hdr = hdr;
@@ -282,7 +317,7 @@
res = waveOutPrepareHeader(hout, hdr, sizeof(WAVEHDR));
if (res != MMSYSERR_NOERROR)
{
- error = ErrOutPrepare;
+ mErrorCode = ErrOutPrepare;
return 1;
}
}
@@ -297,7 +332,7 @@
res = waveInOpen(&hinp, WAVE_MAPPER, &fmt, (DWORD)audioInterrupt, (DWORD)this, CALLBACK_FUNCTION);
if (res != MMSYSERR_NOERROR)
{
- error = ErrInpOpen;
+ mErrorCode = ErrInpOpen;
return 1;
}
@@ -321,7 +356,7 @@
res = waveInAddBuffer(hinp, hdr, sizeof(WAVEHDR));
if (res != MMSYSERR_NOERROR)
{
- error = ErrInpPrepare;
+ mErrorCode = ErrInpPrepare;
return 1;
}
}
@@ -332,9 +367,8 @@
return 0;
}
-
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
int tWinAudioPlayer::CloseDsp()
{
// todo: close the device immediately if open
@@ -342,7 +376,6 @@
int i;
MMRESULT res;
-
if (hout_open)
{
hout_open = 0;
@@ -353,13 +386,13 @@
// unprepare headers
for (i = 0; i < BUFCOUNT; i++)
{
- tAudioBuffer *buf = samples.GetBuffer(i);
+ tAudioBuffer *buf = mSamples.GetBuffer(i);
WAVEHDR *hdr = (WAVEHDR *)buf->hdr;
res = waveOutUnprepareHeader(hout, hdr, sizeof(WAVEHDR));
if (res != MMSYSERR_NOERROR)
{
- error = ErrOutUnprepare;
+ mErrorCode = ErrOutUnprepare;
return 1;
}
delete hdr;
@@ -384,7 +417,7 @@
res = waveInUnprepareHeader(hinp, (WAVEHDR *)buf->hdr, sizeof(WAVEHDR));
if (res != MMSYSERR_NOERROR)
{
- error = ErrInpUnprepare;
+ mErrorCode = ErrInpUnprepare;
return 1;
}
delete buf->hdr;
@@ -397,16 +430,23 @@
return 0;
}
-
-void FAR PASCAL audioInterrupt(HWAVEOUT hout, UINT wMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void FAR PASCAL audioInterrupt(
+ HWAVEOUT hout,
+ UINT wMsg,
+ DWORD dwUser,
+ DWORD dw1,
+ DWORD dw2)
{
if (wMsg == MM_WOM_DONE || wMsg == MM_WIM_DATA)
+ {
((tWinAudioPlayer *)dwUser)->AudioCallback(wMsg);
+ }
}
-
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::AudioCallback(UINT wMsg)
{
// async called by driver when the driver has processed a buffer completely
@@ -416,8 +456,8 @@
{
blocks_played ++;
play_buffers_needed ++;
- tAudioBuffer *buf = samples.driv_buffers.Get();
- samples.free_buffers.Put(buf);
+ tAudioBuffer *buf = mSamples.driv_buffers.Get();
+ mSamples.free_buffers.Put(buf);
}
if (hinp_open && wMsg == MM_WIM_DATA)
{
@@ -426,10 +466,8 @@
LeaveCriticalSection(&mutex);
}
-
-
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::StartAudio()
{
// async called by driver to start audio in sync with midi
@@ -445,30 +483,37 @@
}
}
-
+//-----------------------------------------------------------------------------
+// Description:
+// Send the sample set to driver.
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::WriteBuffers()
{
if (audio_enabled && hout_open)
{
- tAudioBuffer *buf;
- while ((buf = samples.full_buffers.Get()) != 0)
+ tAudioBuffer* pAudioBuffer;
+ while ((pAudioBuffer = mSamples.full_buffers.Get()) != 0)
{
- if (waveOutWrite(hout, buf->hdr, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
+ if (
+ waveOutWrite(
+ hout,
+ pAudioBuffer->hdr,
+ sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
{
- samples.driv_buffers.Put(buf);
- -- play_buffers_needed;
+ mSamples.driv_buffers.Put(pAudioBuffer);
+ --play_buffers_needed;
}
else
{
- samples.full_buffers.UnGet(buf);
+ mSamples.full_buffers.UnGet(pAudioBuffer);
break;
}
}
}
}
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::Notify()
{
if (audio_enabled)
@@ -477,12 +522,14 @@
if (hout_open)
{
- samples.FillBuffers(OutClock);
+ mSamples.FillBuffers(OutClock);
if (play_buffers_needed > 0) // dont trigger start play by accident
+ {
WriteBuffers();
+ }
// midi time correction
- if (can_sync && samples.softsync)
+ if (mCanSynchronize && mSamples.softsync)
{
MMTIME mmtime;
MMRESULT res;
@@ -490,11 +537,14 @@
res = waveOutGetPosition(hout, &mmtime, sizeof(mmtime));
if (res == MMSYSERR_NOERROR && mmtime.wType == TIME_SAMPLES)
{
- long time_now = (long)timeGetTime();
- long audio_now = (long)((double)start_time + (double)mmtime.u.sample * 1000.0 / (double)samples.speed);
+ long time_now = (long)timeGetTime();
+ long audio_now =
+ (long)((double)start_time + 1000.0 * mmtime.u.sample / mSamples.speed);
+
// low pass filter for time-correction (not really necessary)
const long low = 50;
- state->time_correction = (low * state->time_correction + (100 - low) * (audio_now - time_now) ) / 100L;
+ state->time_correction =
+ (low * state->time_correction + (100 - low) * (audio_now - time_now) ) / 100L;
}
}
}
@@ -512,9 +562,9 @@
tAudioBuffer *buf = recbuffers.RequestBuffer();
buf->hdr = hdr;
- hdr->lpData = (LPSTR)buf->data;
- hdr->dwBufferLength = BUFBYTES; // length, in bytes, of the buffer
- hdr->dwFlags = 0; // see below
+ hdr->lpData = (LPSTR)buf->data;
+ hdr->dwBufferLength = BUFBYTES; // length, in bytes, of the buffer
+ hdr->dwFlags = 0;
if (waveInPrepareHeader(hinp, hdr, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
{
@@ -522,10 +572,12 @@
record_buffers_needed --;
}
else
+ {
break;
+ }
}
- if (can_sync && samples.softsync && !hout_open)
+ if (mCanSynchronize && mSamples.softsync && !hout_open)
{
// midi time correction
MMTIME mmtime;
@@ -534,8 +586,9 @@
res = waveInGetPosition(hinp, &mmtime, sizeof(mmtime));
if (res == MMSYSERR_NOERROR && mmtime.wType == TIME_SAMPLES)
{
- long time_now = (long)timeGetTime();
- long audio_now = (long)((double)state->start_time + (double)mmtime.u.sample * 1000.0 / (double)samples.speed);
+ long time_now = (long)timeGetTime();
+ long audio_now =
+ (long)((double)state->start_time + 1000.0 * mmtime.u.sample / mSamples.speed);
// low pass filter for time-correction (not really necessary)
const long low = 50;
state->time_correction = (low * state->time_correction + (100 - low) * (audio_now - time_now) ) / 100L;
@@ -549,34 +602,34 @@
tWinIntPlayer::Notify();
}
-
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::StartPlay(long Clock, long LoopClock, int Continue)
{
- samples.StartPlay(Clock);
+ mSamples.StartPlay(Clock);
tWinIntPlayer::StartPlay(Clock, LoopClock, Continue);
if (!audio_enabled)
return;
- delete listener;
+ delete mpListener;
start_clock = Clock;
start_time = state->start_time;
- samples.ResetBuffers(AudioBuffer, start_clock, state->ticks_per_minute);
- samples.FillBuffers(OutClock);
+ mSamples.ResetBuffers(AudioBuffer, start_clock, state->ticks_per_minute);
+ mSamples.FillBuffers(OutClock);
OpenDsp();
}
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::StopPlay()
{
tWinIntPlayer::StopPlay();
CloseDsp();
- samples.StopPlay();
+ mSamples.StopPlay();
if (RecordMode())
{
long frc = rec_info->mFromClock;
@@ -586,33 +639,44 @@
long play_clock = Time2Clock(state->play_time);
if (toc > play_clock)
toc = play_clock;
- samples.SaveRecordingDlg(frc, toc, recbuffers);
+ mSamples.SaveRecordingDlg(frc, toc, recbuffers);
}
recbuffers.Clear();
}
-
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::ListenAudio(int key, int start_stop_mode)
{
if (!audio_enabled)
+ {
return;
+ }
- // play audio file from piano roll
+ // Play the audio file from the piano roll.
if (Playing)
+ {
return;
- // when already listening then stop listening
- if (listener)
+ }
+
+ // If already listening then stop listening.
+ if (mpListener)
{
- delete listener;
+ delete mpListener;
if (start_stop_mode)
+ {
return;
+ }
}
if (key < 0)
+ {
return;
- listener = new tAudioListener(this, key);
+ }
+ mpListener = new tAudioListener(this, key);
}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
void tWinAudioPlayer::ListenAudio(tSample &spl, long fr_smpl, long to_smpl)
{
if (!audio_enabled)
@@ -621,21 +685,27 @@
if (Playing)
return;
// when already listening then stop listening
- if (listener)
- delete listener;
- listener = new tAudioListener(this, spl, fr_smpl, to_smpl);
+ if (mpListener)
+ {
+ delete mpListener;
+ }
+ mpListener = new tAudioListener(this, spl, fr_smpl, to_smpl);
}
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
long tWinAudioPlayer::GetListenerPlayPosition()
{
- if (!listener)
+ if (!mpListener)
+ {
return -1L;
- return listener->GetPlayPosition();
+ }
+ return mpListener->GetPlayPosition();
}
-
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
int tWinAudioPlayer::RecordMode() const
{
return rec_info != 0 && rec_info->mpTrack->GetAudioMode();
}
-
Modified: trunk/jazz/src/mswin/WindowsAudioInterface.h
===================================================================
--- trunk/jazz/src/mswin/WindowsAudioInterface.h 2008-04-05 20:12:11 UTC (rev 398)
+++ trunk/jazz/src/mswin/WindowsAudioInterface.h 2008-04-05 23:43:43 UTC (rev 399)
@@ -35,77 +35,125 @@
class tWinAudioPlayer : public tWinIntPlayer
{
friend class tAudioListener;
+
public:
- tWinAudioPlayer(JZSong *song);
+
+ enum TEErrorCode
+ {
+ NoError,
+ ErrOutOpen,
+ ErrOutPrepare,
+ ErrOutUnprepare,
+ ErrInpOpen,
+ ErrInpPrepare,
+ ErrInpUnprepare,
+ ErrCapGet,
+ ErrCapSync
+ };
+
+ tWinAudioPlayer(JZSong* pSong);
+
virtual ~tWinAudioPlayer();
+
int LoadSamples(const char *filename);
+
virtual void Notify();
+
virtual void StartPlay(long Clock, long LoopClock = 0, int Continue = 0);
+
virtual void StopPlay();
+
virtual void StartAudio(); // called async by driver
- virtual int Installed() { return installed && tWinIntPlayer::Installed(); }
- virtual int GetAudioEnabled() const { return audio_enabled; }
- virtual void SetAudioEnabled(int x) { audio_enabled = x; }
+
+ virtual int Installed()
+ {
+ return installed && tWinIntPlayer::Installed();
+ }
+
+ virtual int GetAudioEnabled() const
+ {
+ return audio_enabled;
+ }
+
+ virtual void SetAudioEnabled(int x)
+ {
+ audio_enabled = x;
+ }
+
virtual void ListenAudio(int key, int start_stop_mode = 1);
+
virtual void ListenAudio(tSample &spl, long fr_smpl, long to_smpl);
+
virtual long GetListenerPlayPosition();
- virtual bool IsListening() const {
- return listener != 0;
+ virtual bool IsListening() const
+ {
+ return mpListener != 0;
}
// for recording
int RecordMode() const;
- int PlaybackMode() const {
- return !RecordMode() || can_duplex;
+
+ int PlaybackMode() const
+ {
+ return !RecordMode() || mCanDuplex;
}
- enum ErrorCode {
- NoError,
- ErrOutOpen, ErrOutPrepare, ErrOutUnprepare,
- ErrInpOpen, ErrInpPrepare, ErrInpUnprepare,
- ErrCapGet, ErrCapSync
- };
- ErrorCode GetError() {
- return error;
+ TEErrorCode GetError()
+ {
+ return mErrorCode;
}
+
virtual void ShowError();
private:
- ErrorCode error;
- int can_duplex; // TRUE = can do full duplex record/play
- int can_sync; // TRUE = can determine exact output play position
+ // ms specific
+ friend void FAR PASCAL audioInterrupt(
+ HWAVEOUT,
+ UINT,
+ DWORD,
+ DWORD,
+ DWORD);
- int OpenDsp(); // 0 = ok
- int CloseDsp(); // 0 = ok
+ // Description:
+ // Send the sample set to driver.
+ void WriteBuffers();
- int installed;
- int audio_enabled; // 0 means midi only
+ void AudioCallback(UINT msg);
+
+ TEErrorCode mErrorCode;
+
+ // Indicates if full duplex record/play is possible.
+ bool mCanDuplex;
+
+ // Indicates if the exact output play position can be determined.
+ bool mCanSynchronize;
+
+ int OpenDsp(); // 0 = ok
+ int CloseDsp(); // 0 = ok
+
+ int installed;
+ int audio_enabled; // 0 means midi only
long blocks_played; // # of blocks written to device
- int play_buffers_needed; // driver requests more output buffers
+ int play_buffers_needed; // driver requests more output buffers
long start_clock; // when did play start
long start_time; // play start time (not altered by SetTempo)
- tAudioListener *listener;
+ tAudioListener* mpListener;
- // ms specific
- friend void FAR PASCAL audioInterrupt(HWAVEOUT, UINT, DWORD, DWORD, DWORD);
HWAVEOUT hout;
HWAVEIN hinp;
- void WriteBuffers(); // send samples.full_buffers to driver
- void AudioCallback(UINT msg);
- int hout_open; // true = playback device opended successful
- int hinp_open; // true = recording device opended successful
+ int hout_open; // true = playback device opended successful
+ int hinp_open; // true = recording device opended successful
tAudioRecordBuffer recbuffers;
- int record_buffers_needed; // driver needs more buffers
+ int record_buffers_needed; // driver needs more buffers
// a semaphor for thread synchronization. Since Notify() and
// the audio callback are not time critical, its safe to
// let them wait for each other.
CRITICAL_SECTION ...
[truncated message content] |