Improved design and made the changes to tone characteristics update on next change.

This commit is contained in:
Mark Hamann 2016-02-26 08:08:53 -08:00
parent e778b1d1b6
commit 8ad36377f2
3 changed files with 125 additions and 48 deletions

View file

@ -119,8 +119,9 @@ namespace MorseTrainer
_runner.StopDelayEnter += _runner_StopDelayEnter;
_runner.StopDelayExit += _runner_StopDelayExit;
_runner.Abort += _runner_Abort;
_player.QueueEmpty += _player_QueueEmpty;
_player.Dequeued += _player_Dequeued;
_player.PlayingFinished += _player_PlayingFinished;
_toneGenerator.UpdateRequired += _toneGenerator_UpdateRequired;
cmbKoch.Items.Clear();
for (int i = 0; i < Koch.Length; ++i)
@ -216,8 +217,7 @@ namespace MorseTrainer
{
if (_runner.IsRunning)
{
_pendingWavestream = null;
_player.Clear();
_player.ClearQueue();
btnStartStop.Enabled = false;
_runner.RequestStop();
}
@ -234,13 +234,18 @@ namespace MorseTrainer
private void FirstWaveReadyCallback(IAsyncResult result)
{
_pendingWavestream = (WaveStream)result.AsyncState;
WaveStream waveStream = (WaveStream)result.AsyncState;
_player.Enqueue(waveStream);
_runner.RequestStart();
}
private void WaveReadyCallback(IAsyncResult result)
{
_pendingWavestream = (WaveStream)result.AsyncState;
WaveStream waveStream = (WaveStream)result.AsyncState;
if (waveStream != null)
{
_player.Enqueue(waveStream);
}
}
private void _runner_StartDelayEnter(object sender, EventArgs e)
@ -253,21 +258,28 @@ namespace MorseTrainer
private void _runner_MorseEnter(object sender, EventArgs e)
{
_player.Start(_pendingWavestream);
_pendingWavestream = null;
_player.Start();
String word = _charGenerator.CreateRandomString();
_builder.StartBuildAsync(word, new AsyncCallback(WaveReadyCallback));
}
private void _player_QueueEmpty(object sender, EventArgs e)
private void _player_Dequeued(object sender, EventArgs e)
{
if (_runner.ContinueMorse)
{
_player.Enqueue(_pendingWavestream);
_builder.StartBuildAsync(_charGenerator.CreateRandomString(), new AsyncCallback(WaveReadyCallback));
}
}
private void _toneGenerator_UpdateRequired(object sender, EventArgs e)
{
// This indicates that the tone has changed. If we are currently sending code,
// we need to remove any queued tones and in progress tones and send new tones instead
_toneGenerator.Update();
_player.ClearQueue();
_builder.StartBuildAsync(_charGenerator.CreateRandomString(), new AsyncCallback(WaveReadyCallback));
}
private void _player_PlayingFinished(object sender, EventArgs e)
{
_runner.AcknowledgeSendEnd();
@ -275,6 +287,8 @@ namespace MorseTrainer
private void _runner_MorseExit(object sender, EventArgs e)
{
_player.Stop();
_player.ClearQueue();
}
private void _runner_StopDelayEnter(object sender, EventArgs e)
@ -1251,7 +1265,6 @@ namespace MorseTrainer
private Runner _runner;
private Analyzer _analyzer;
private StringBuilder _recorded;
private WaveStream _pendingWavestream;
#endregion
}

View file

@ -36,6 +36,7 @@ namespace MorseTrainer
/// </summary>
public SoundPlayerAsync()
{
_sending = false;
_mediaSoundPlayer = new System.Media.SoundPlayer();
_queue = new Queue<WaveStream>();
_sentString = new StringBuilder();
@ -50,24 +51,36 @@ namespace MorseTrainer
{
while (!_stopThread)
{
WaveStream waveToPlay = Dequeue();
if (waveToPlay != null)
bool go = false;
lock (this)
{
_mediaSoundPlayer.Stream = waveToPlay.Stream;
_mediaSoundPlayer.Load();
_mediaSoundPlayer.PlaySync();
_sentString.Append(waveToPlay.Text);
_sentString.Append(' ');
// All done
if (Count == 0)
if (!_sending)
{
OnPlayingFinished();
System.Threading.Monitor.Wait(this);
}
go = _sending && !_stopThread;
}
if (go)
{
WaveStream waveToPlay = Dequeue();
if (waveToPlay != null)
{
_mediaSoundPlayer.Stream = waveToPlay.Stream;
_mediaSoundPlayer.Load();
_mediaSoundPlayer.PlaySync();
_sentString.Append(waveToPlay.Text);
_sentString.Append(' ');
// All done
if (Count == 0)
{
OnPlayingFinished();
}
}
}
}
lock(this)
{
_stopped = true;
_threadStopped = true;
System.Threading.Monitor.Pulse(this);
}
}
@ -86,7 +99,7 @@ namespace MorseTrainer
wave = _queue.Dequeue();
if (_queue.Count == 0)
{
OnQueueEmpty();
OnDequeued();
}
}
}
@ -96,11 +109,21 @@ namespace MorseTrainer
/// <summary>
/// Puts a WAV onto the queue and resets the strings
/// </summary>
/// <param name="wave">A WaveStream</param>
public void Start(WaveStream wave)
public void Start()
{
Enqueue(wave);
_sentString.Clear();
lock(this)
{
_sending = true;
_sentString.Clear();
}
}
public void Stop()
{
lock(this)
{
_sending = false;
}
}
/// <summary>
@ -129,9 +152,9 @@ namespace MorseTrainer
}
/// <summary>
/// Clear all waves from the queue when aborting
/// ClearQueue all waves from the queue when aborting
/// </summary>
public void Clear()
public void ClearQueue()
{
lock(this)
{
@ -168,12 +191,12 @@ namespace MorseTrainer
}
/// <summary>
/// The queue has been emptied. Action in this should be quick
/// The queue has been dequeued. Action in this should be quick
/// </summary>
public event EventHandler QueueEmpty;
protected void OnQueueEmpty()
public event EventHandler Dequeued;
protected void OnDequeued()
{
EventHandler handler = QueueEmpty;
EventHandler handler = Dequeued;
if (handler != null)
{
handler(this, EventArgs.Empty);
@ -190,10 +213,10 @@ namespace MorseTrainer
if (_thread != null && !_stopThread)
{
_stopThread = true;
_stopped = false;
_threadStopped = false;
_queue.Clear();
System.Threading.Monitor.Pulse(this);
if (!_stopped)
if (!_threadStopped)
{
System.Threading.Monitor.Wait(this);
}
@ -206,7 +229,9 @@ namespace MorseTrainer
private System.Threading.Thread _thread;
private bool _stopThread;
private bool _stopped;
private bool _threadStopped;
private bool _sending;
private Queue<WaveStream> _queue;
private System.Media.SoundPlayer _mediaSoundPlayer;
private StringBuilder _sentString;

View file

@ -85,6 +85,7 @@ namespace MorseTrainer
_WPM = 0;
_farnsworthWPM = 0;
_volume = 0.0f;
_updateRequired = true;
}
private float WpmToMillesecPerElement(float wpm)
@ -102,24 +103,57 @@ namespace MorseTrainer
/// </summary>
public void Update()
{
// changing tone frequency or WPM will cause the tones to be regenerated
if (_frequency == 0 || _frequency != _newFrequency || _newWPM != _WPM || _newVolume != _volume)
if (_updateRequired)
{
_volume = _newVolume;
_frequency = _newFrequency;
_WPM = _newWPM;
// ms per element = WPM * 1000 ms per sec / 60 words per second / 50 elements
_msPerElement = WpmToMillesecPerElement(_WPM);
_updateRequired = false;
float samplesPerCycle = SAMPLES_PER_SECOND / _frequency;
// changing tone frequency or WPM will cause the tones to be regenerated
if (_frequency == 0 || _frequency != _newFrequency || _newWPM != _WPM || _newVolume != _volume)
{
_volume = _newVolume;
_frequency = _newFrequency;
_WPM = _newWPM;
// ms per element = WPM * 1000 ms per sec / 60 words per second / 50 elements
_msPerElement = WpmToMillesecPerElement(_WPM);
_samplesPerCycle = (UInt16)(samplesPerCycle + 0.5);
CreateTones();
float samplesPerCycle = SAMPLES_PER_SECOND / _frequency;
_samplesPerCycle = (UInt16)(samplesPerCycle + 0.5);
CreateTones();
}
if (_farnsworthWPM == 0 || _farnsworthWPM != _newFarnsworthWPM)
{
_farnsworthWPM = _newFarnsworthWPM;
_msPerFarnsworthElement = WpmToMillesecPerElement(_farnsworthWPM);
}
}
if (_farnsworthWPM == 0 || _farnsworthWPM != _newFarnsworthWPM)
}
/// <summary>
/// The user has made a change that will require an update
/// </summary>
public event EventHandler UpdateRequired;
protected void OnUpdateRequired()
{
if (!_updateRequired)
{
_farnsworthWPM = _newFarnsworthWPM;
_msPerFarnsworthElement = WpmToMillesecPerElement(_farnsworthWPM);
_updateRequired = true;
EventHandler handler = UpdateRequired;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
/// <summary>
/// Gets if there is a required update to generated tones
/// </summary>
public bool IsUpdateRequired
{
get
{
return _updateRequired;
}
}
@ -150,6 +184,7 @@ namespace MorseTrainer
throw new ArgumentOutOfRangeException("Frequency");
}
_newFrequency = value;
OnUpdateRequired();
}
}
@ -169,6 +204,7 @@ namespace MorseTrainer
throw new ArgumentOutOfRangeException("Volume");
}
_newVolume = value;
OnUpdateRequired();
}
}
@ -199,6 +235,7 @@ namespace MorseTrainer
throw new ArgumentOutOfRangeException("WPM");
}
_newWPM = (float)Math.Round(value * 2) / 2;
OnUpdateRequired();
}
}
@ -229,6 +266,7 @@ namespace MorseTrainer
throw new ArgumentOutOfRangeException("WPM");
}
_newFarnsworthWPM = (float)Math.Round(value * 2) / 2;
OnUpdateRequired();
}
}
@ -382,6 +420,7 @@ namespace MorseTrainer
return CreateSpace(difference);
}
private bool _updateRequired;
private UInt16 _frequency;
private UInt16 _newFrequency;
private float _WPM;