PowerSDR-2.8.0-SDR1000/Source/Console/wave.cs

3482 lines
132 KiB
C#

//=================================================================
// wave.cs
//=================================================================
// PowerSDR is a C# implementation of a Software Defined Radio.
// Copyright (C) 2003-2013 FlexRadio Systems
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// You may contact us via email at: gpl@flexradio.com.
// Paper mail may be sent to:
// FlexRadio Systems
// 4616 W. Howard Lane Suite 1-150
// Austin, TX 78728
// USA
//=================================================================
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Collections;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
//reference Nuget Package NAudio.Lame
using NAudio;
using NAudio.Wave;
using NAudio.Lame;
using System.Collections.Generic;
namespace PowerSDR
{
sealed public class WaveControl : System.Windows.Forms.Form
{
#region Variable Declaration
private static Bitmap ke9ns_bmp; // ke9ns add call sign waterfall tx id
private Console console;
private WaveOptions WaveOptions;
private ArrayList file_list;
private string wave_folder = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic) + "\\PowerSDR";
private System.Windows.Forms.OpenFileDialog openFileDialog1;
private System.Windows.Forms.CheckBoxTS checkBoxPlay;
private System.Windows.Forms.GroupBoxTS groupBox2;
public CheckBoxTS checkBoxRecord;
private System.Windows.Forms.GroupBoxTS grpPlayback;
private System.Windows.Forms.ButtonTS btnStop;
private System.Windows.Forms.CheckBoxTS checkBoxPause;
private System.Windows.Forms.ButtonTS btnPrevious;
private System.Windows.Forms.ButtonTS btnNext;
public ListBox lstPlaylist;
private System.Windows.Forms.ButtonTS btnAdd;
private System.Windows.Forms.ButtonTS btnRemove;
private System.Windows.Forms.CheckBoxTS checkBoxRandom;
private System.Windows.Forms.GroupBox grpPlaylist;
private System.Windows.Forms.TextBoxTS txtCurrentFile;
private System.Windows.Forms.LabelTS lblCurrentlyPlaying;
private System.Windows.Forms.CheckBoxTS checkBoxLoop;
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem mnuWaveOptions;
private System.Windows.Forms.NumericUpDownTS udPreamp;
private System.Windows.Forms.GroupBoxTS groupBoxTS1;
private System.Windows.Forms.CheckBoxTS chkQuickRec;
private System.Windows.Forms.CheckBoxTS chkQuickPlay;
private System.Windows.Forms.TrackBar tbPreamp;
#endregion
public CheckBoxTS TXIDBoxTS; // ke9ns add
public CheckBoxTS createBoxTS; // ke9ns add
public CheckBoxTS chkQuickAudioFolder; // ke9ns add
private TextBox textBox1;
public CheckBoxTS chkBoxMP3;
public CheckBoxTS checkBoxVoice;
public CheckBoxTS checkBoxCW;
public CheckBoxTS checkBoxCQ;
private ToolTip toolTip1;
private GroupBoxTS groupBoxTS2;
public CheckBoxTS checkBoxTS1;
public CheckBoxTS checkBoxTS2;
public CheckBoxTS chkAlwaysOnTop;
private IContainer components;
#region Constructor and Destructor
public WaveControl(Console c)
{
InitializeComponent();
console = c;
if (!Directory.Exists(wave_folder))
{
// create PowerSDR audio folder if it does not exist
Directory.CreateDirectory(wave_folder);
}
// openFileDialog1.InitialDirectory = console.AppDataPath;
openFileDialog1.InitialDirectory = String.Empty;
openFileDialog1.InitialDirectory = wave_folder;
file_list = new ArrayList();
currently_playing = -1;
WaveOptions = new WaveOptions();
this.ActiveControl = btnAdd;
Common.RestoreForm(this, "WaveOptions", false);
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WaveControl));
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.grpPlaylist = new System.Windows.Forms.GroupBox();
this.checkBoxRandom = new System.Windows.Forms.CheckBoxTS();
this.checkBoxLoop = new System.Windows.Forms.CheckBoxTS();
this.btnAdd = new System.Windows.Forms.ButtonTS();
this.lstPlaylist = new System.Windows.Forms.ListBox();
this.btnRemove = new System.Windows.Forms.ButtonTS();
this.mainMenu1 = new System.Windows.Forms.MainMenu(this.components);
this.mnuWaveOptions = new System.Windows.Forms.MenuItem();
this.textBox1 = new System.Windows.Forms.TextBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.checkBoxTS1 = new System.Windows.Forms.CheckBoxTS();
this.checkBoxTS2 = new System.Windows.Forms.CheckBoxTS();
this.checkBoxVoice = new System.Windows.Forms.CheckBoxTS();
this.checkBoxCQ = new System.Windows.Forms.CheckBoxTS();
this.checkBoxCW = new System.Windows.Forms.CheckBoxTS();
this.chkQuickAudioFolder = new System.Windows.Forms.CheckBoxTS();
this.groupBoxTS2 = new System.Windows.Forms.GroupBoxTS();
this.chkBoxMP3 = new System.Windows.Forms.CheckBoxTS();
this.createBoxTS = new System.Windows.Forms.CheckBoxTS();
this.TXIDBoxTS = new System.Windows.Forms.CheckBoxTS();
this.chkQuickPlay = new System.Windows.Forms.CheckBoxTS();
this.chkQuickRec = new System.Windows.Forms.CheckBoxTS();
this.groupBoxTS1 = new System.Windows.Forms.GroupBoxTS();
this.tbPreamp = new System.Windows.Forms.TrackBar();
this.udPreamp = new System.Windows.Forms.NumericUpDownTS();
this.groupBox2 = new System.Windows.Forms.GroupBoxTS();
this.checkBoxRecord = new System.Windows.Forms.CheckBoxTS();
this.grpPlayback = new System.Windows.Forms.GroupBoxTS();
this.txtCurrentFile = new System.Windows.Forms.TextBoxTS();
this.lblCurrentlyPlaying = new System.Windows.Forms.LabelTS();
this.btnNext = new System.Windows.Forms.ButtonTS();
this.btnPrevious = new System.Windows.Forms.ButtonTS();
this.checkBoxPause = new System.Windows.Forms.CheckBoxTS();
this.btnStop = new System.Windows.Forms.ButtonTS();
this.checkBoxPlay = new System.Windows.Forms.CheckBoxTS();
this.chkAlwaysOnTop = new System.Windows.Forms.CheckBoxTS();
this.grpPlaylist.SuspendLayout();
this.groupBoxTS2.SuspendLayout();
this.groupBoxTS1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.tbPreamp)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.udPreamp)).BeginInit();
this.groupBox2.SuspendLayout();
this.grpPlayback.SuspendLayout();
this.SuspendLayout();
//
// openFileDialog1
//
this.openFileDialog1.Filter = "WAV files (*.wav)|*.wav|All files (*.*)|*.*";
this.openFileDialog1.Multiselect = true;
this.openFileDialog1.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog1_FileOk);
//
// grpPlaylist
//
this.grpPlaylist.Controls.Add(this.checkBoxRandom);
this.grpPlaylist.Controls.Add(this.checkBoxLoop);
this.grpPlaylist.Controls.Add(this.btnAdd);
this.grpPlaylist.Controls.Add(this.lstPlaylist);
this.grpPlaylist.Controls.Add(this.btnRemove);
this.grpPlaylist.Location = new System.Drawing.Point(8, 104);
this.grpPlaylist.Name = "grpPlaylist";
this.grpPlaylist.Size = new System.Drawing.Size(304, 184);
this.grpPlaylist.TabIndex = 6;
this.grpPlaylist.TabStop = false;
this.grpPlaylist.Text = "Playlist";
//
// checkBoxRandom
//
this.checkBoxRandom.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxRandom.Enabled = false;
this.checkBoxRandom.Image = null;
this.checkBoxRandom.Location = new System.Drawing.Point(224, 24);
this.checkBoxRandom.Name = "checkBoxRandom";
this.checkBoxRandom.Size = new System.Drawing.Size(56, 23);
this.checkBoxRandom.TabIndex = 13;
this.checkBoxRandom.Text = "Random";
this.checkBoxRandom.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.checkBoxRandom.Visible = false;
this.checkBoxRandom.CheckedChanged += new System.EventHandler(this.checkBoxRandom_CheckedChanged);
//
// checkBoxLoop
//
this.checkBoxLoop.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxLoop.Enabled = false;
this.checkBoxLoop.Image = null;
this.checkBoxLoop.Location = new System.Drawing.Point(176, 24);
this.checkBoxLoop.Name = "checkBoxLoop";
this.checkBoxLoop.Size = new System.Drawing.Size(40, 23);
this.checkBoxLoop.TabIndex = 12;
this.checkBoxLoop.Text = "Loop";
this.checkBoxLoop.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.checkBoxLoop.CheckedChanged += new System.EventHandler(this.checkBoxLoop_CheckedChanged);
//
// btnAdd
//
this.btnAdd.Image = null;
this.btnAdd.Location = new System.Drawing.Point(24, 24);
this.btnAdd.Name = "btnAdd";
this.btnAdd.Size = new System.Drawing.Size(48, 23);
this.btnAdd.TabIndex = 6;
this.btnAdd.Text = "Add...";
this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
//
// lstPlaylist
//
this.lstPlaylist.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.lstPlaylist.Location = new System.Drawing.Point(16, 56);
this.lstPlaylist.Name = "lstPlaylist";
this.lstPlaylist.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
this.lstPlaylist.Size = new System.Drawing.Size(272, 108);
this.lstPlaylist.TabIndex = 0;
this.lstPlaylist.SelectedIndexChanged += new System.EventHandler(this.lstPlaylist_SelectedIndexChanged);
this.lstPlaylist.DoubleClick += new System.EventHandler(this.lstPlaylist_DoubleClick);
//
// btnRemove
//
this.btnRemove.Enabled = false;
this.btnRemove.Image = null;
this.btnRemove.Location = new System.Drawing.Point(80, 24);
this.btnRemove.Name = "btnRemove";
this.btnRemove.Size = new System.Drawing.Size(56, 23);
this.btnRemove.TabIndex = 11;
this.btnRemove.Text = "Remove";
this.btnRemove.Click += new System.EventHandler(this.btnRemove_Click);
//
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.mnuWaveOptions});
//
// mnuWaveOptions
//
this.mnuWaveOptions.Index = 0;
this.mnuWaveOptions.Text = "Options";
this.mnuWaveOptions.Click += new System.EventHandler(this.mnuWaveOptions_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(8, 294);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(392, 62);
this.textBox1.TabIndex = 59;
//
// toolTip1
//
this.toolTip1.AutomaticDelay = 200;
this.toolTip1.AutoPopDelay = 12000;
this.toolTip1.InitialDelay = 500;
this.toolTip1.ReshowDelay = 40;
//
// checkBoxTS1
//
this.checkBoxTS1.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxTS1.Image = null;
this.checkBoxTS1.Location = new System.Drawing.Point(318, 431);
this.checkBoxTS1.Name = "checkBoxTS1";
this.checkBoxTS1.Size = new System.Drawing.Size(72, 24);
this.checkBoxTS1.TabIndex = 64;
this.checkBoxTS1.Text = "MP3 Folder";
this.checkBoxTS1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.toolTip1.SetToolTip(this.checkBoxTS1, "Opens QuickAudio folder containing MP3 files");
this.checkBoxTS1.CheckedChanged += new System.EventHandler(this.checkBoxTS1_CheckedChanged);
//
// checkBoxTS2
//
this.checkBoxTS2.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxTS2.Image = null;
this.checkBoxTS2.Location = new System.Drawing.Point(204, 25);
this.checkBoxTS2.Name = "checkBoxTS2";
this.checkBoxTS2.Size = new System.Drawing.Size(72, 24);
this.checkBoxTS2.TabIndex = 64;
this.checkBoxTS2.Text = "Reply";
this.checkBoxTS2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.toolTip1.SetToolTip(this.checkBoxTS2, resources.GetString("checkBoxTS2.ToolTip"));
this.checkBoxTS2.CheckedChanged += new System.EventHandler(this.checkBoxTS2_CheckedChanged);
//
// checkBoxVoice
//
this.checkBoxVoice.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxVoice.Image = null;
this.checkBoxVoice.Location = new System.Drawing.Point(21, 25);
this.checkBoxVoice.Name = "checkBoxVoice";
this.checkBoxVoice.Size = new System.Drawing.Size(72, 24);
this.checkBoxVoice.TabIndex = 61;
this.checkBoxVoice.Text = "Voice ID";
this.checkBoxVoice.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.toolTip1.SetToolTip(this.checkBoxVoice, "Record a Voice ID of your callsign (in SSB).\r\nUsed by the voID Timer feature on t" +
"he main console.\r\n\r\nClick to Start/Stop record a CW ID File: IDTIMER.wav\r\n");
this.checkBoxVoice.CheckedChanged += new System.EventHandler(this.checkBoxVoice_CheckedChanged);
//
// checkBoxCQ
//
this.checkBoxCQ.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxCQ.Image = null;
this.checkBoxCQ.Location = new System.Drawing.Point(292, 25);
this.checkBoxCQ.Name = "checkBoxCQ";
this.checkBoxCQ.Size = new System.Drawing.Size(72, 24);
this.checkBoxCQ.TabIndex = 63;
this.checkBoxCQ.Text = "CQ CQ";
this.checkBoxCQ.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.toolTip1.SetToolTip(this.checkBoxCQ, resources.GetString("checkBoxCQ.ToolTip"));
this.checkBoxCQ.CheckedChanged += new System.EventHandler(this.checkBoxCQ_CheckedChanged);
//
// checkBoxCW
//
this.checkBoxCW.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxCW.Image = null;
this.checkBoxCW.Location = new System.Drawing.Point(110, 25);
this.checkBoxCW.Name = "checkBoxCW";
this.checkBoxCW.Size = new System.Drawing.Size(72, 24);
this.checkBoxCW.TabIndex = 62;
this.checkBoxCW.Text = "CW ID";
this.checkBoxCW.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.toolTip1.SetToolTip(this.checkBoxCW, "Record a CW ID of your callsign.\r\nUsed by the cwID Timer feature on the main coso" +
"le.\r\n\r\nClick to Start/Stop record a CW ID File: IDTIMERCW.wav\r\n\r\nMake sure to be" +
" in CW mode and open CWX panel.");
this.checkBoxCW.CheckedChanged += new System.EventHandler(this.checkBoxCW_CheckedChanged);
//
// chkQuickAudioFolder
//
this.chkQuickAudioFolder.Checked = true;
this.chkQuickAudioFolder.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkQuickAudioFolder.Image = null;
this.chkQuickAudioFolder.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.chkQuickAudioFolder.Location = new System.Drawing.Point(8, 431);
this.chkQuickAudioFolder.Name = "chkQuickAudioFolder";
this.chkQuickAudioFolder.Size = new System.Drawing.Size(148, 26);
this.chkQuickAudioFolder.TabIndex = 58;
this.chkQuickAudioFolder.Text = "QuickAudio Save Folder";
this.chkQuickAudioFolder.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.toolTip1.SetToolTip(this.chkQuickAudioFolder, "This box should remain Check.\r\nThis allows multiple QuickAudio files to be stored" +
"\r\nand puts them into a folder called \"QuickAudio\"");
this.chkQuickAudioFolder.CheckedChanged += new System.EventHandler(this.chkQuickAudioFolder_CheckedChanged);
//
// groupBoxTS2
//
this.groupBoxTS2.Controls.Add(this.checkBoxTS2);
this.groupBoxTS2.Controls.Add(this.checkBoxVoice);
this.groupBoxTS2.Controls.Add(this.checkBoxCQ);
this.groupBoxTS2.Controls.Add(this.checkBoxCW);
this.groupBoxTS2.Location = new System.Drawing.Point(12, 362);
this.groupBoxTS2.Name = "groupBoxTS2";
this.groupBoxTS2.Size = new System.Drawing.Size(388, 59);
this.groupBoxTS2.TabIndex = 11;
this.groupBoxTS2.TabStop = false;
this.groupBoxTS2.Text = "Create Special QuickAudio Files";
//
// chkBoxMP3
//
this.chkBoxMP3.Checked = true;
this.chkBoxMP3.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkBoxMP3.Image = null;
this.chkBoxMP3.Location = new System.Drawing.Point(162, 431);
this.chkBoxMP3.Name = "chkBoxMP3";
this.chkBoxMP3.Size = new System.Drawing.Size(150, 26);
this.chkBoxMP3.TabIndex = 60;
this.chkBoxMP3.Text = "QuickAudio Create MP3\r\n";
this.chkBoxMP3.CheckedChanged += new System.EventHandler(this.chkBoxMP3_CheckedChanged);
//
// createBoxTS
//
this.createBoxTS.Appearance = System.Windows.Forms.Appearance.Button;
this.createBoxTS.Enabled = false;
this.createBoxTS.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.createBoxTS.Image = null;
this.createBoxTS.Location = new System.Drawing.Point(328, 166);
this.createBoxTS.Name = "createBoxTS";
this.createBoxTS.Size = new System.Drawing.Size(72, 24);
this.createBoxTS.TabIndex = 57;
this.createBoxTS.Text = "Create Wtr ID";
this.createBoxTS.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.createBoxTS.Visible = false;
this.createBoxTS.CheckedChanged += new System.EventHandler(this.createBoxTS_CheckedChanged);
//
// TXIDBoxTS
//
this.TXIDBoxTS.Appearance = System.Windows.Forms.Appearance.Button;
this.TXIDBoxTS.Enabled = false;
this.TXIDBoxTS.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.TXIDBoxTS.Image = null;
this.TXIDBoxTS.Location = new System.Drawing.Point(328, 194);
this.TXIDBoxTS.Name = "TXIDBoxTS";
this.TXIDBoxTS.Size = new System.Drawing.Size(72, 24);
this.TXIDBoxTS.TabIndex = 56;
this.TXIDBoxTS.Text = "WaterID Play";
this.TXIDBoxTS.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.TXIDBoxTS.Visible = false;
this.TXIDBoxTS.CheckedChanged += new System.EventHandler(this.TXIDBoxTS_CheckedChanged);
//
// chkQuickPlay
//
this.chkQuickPlay.Appearance = System.Windows.Forms.Appearance.Button;
this.chkQuickPlay.Enabled = false;
this.chkQuickPlay.Image = null;
this.chkQuickPlay.Location = new System.Drawing.Point(328, 256);
this.chkQuickPlay.Name = "chkQuickPlay";
this.chkQuickPlay.Size = new System.Drawing.Size(72, 24);
this.chkQuickPlay.TabIndex = 55;
this.chkQuickPlay.Text = "Quick Play";
this.chkQuickPlay.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.chkQuickPlay.Visible = false;
this.chkQuickPlay.CheckedChanged += new System.EventHandler(this.chkQuickPlay_CheckedChanged);
//
// chkQuickRec
//
this.chkQuickRec.Appearance = System.Windows.Forms.Appearance.Button;
this.chkQuickRec.Image = null;
this.chkQuickRec.Location = new System.Drawing.Point(328, 224);
this.chkQuickRec.Name = "chkQuickRec";
this.chkQuickRec.Size = new System.Drawing.Size(72, 24);
this.chkQuickRec.TabIndex = 54;
this.chkQuickRec.Text = "Quick Rec";
this.chkQuickRec.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.chkQuickRec.Visible = false;
this.chkQuickRec.CheckedChanged += new System.EventHandler(this.chkQuickRec_CheckedChanged);
//
// groupBoxTS1
//
this.groupBoxTS1.Controls.Add(this.tbPreamp);
this.groupBoxTS1.Controls.Add(this.udPreamp);
this.groupBoxTS1.Location = new System.Drawing.Point(320, 80);
this.groupBoxTS1.Name = "groupBoxTS1";
this.groupBoxTS1.Size = new System.Drawing.Size(88, 80);
this.groupBoxTS1.TabIndex = 53;
this.groupBoxTS1.TabStop = false;
this.groupBoxTS1.Text = "TX Gain (dB)";
//
// tbPreamp
//
this.tbPreamp.AutoSize = false;
this.tbPreamp.Location = new System.Drawing.Point(8, 48);
this.tbPreamp.Maximum = 70;
this.tbPreamp.Minimum = -70;
this.tbPreamp.Name = "tbPreamp";
this.tbPreamp.Size = new System.Drawing.Size(72, 16);
this.tbPreamp.TabIndex = 53;
this.tbPreamp.TickFrequency = 35;
this.tbPreamp.Scroll += new System.EventHandler(this.tbPreamp_Scroll);
//
// udPreamp
//
this.udPreamp.BackColor = System.Drawing.SystemColors.Window;
this.udPreamp.ForeColor = System.Drawing.SystemColors.ControlText;
this.udPreamp.Increment = new decimal(new int[] {
1,
0,
0,
0});
this.udPreamp.Location = new System.Drawing.Point(16, 24);
this.udPreamp.Maximum = new decimal(new int[] {
70,
0,
0,
0});
this.udPreamp.Minimum = new decimal(new int[] {
70,
0,
0,
-2147483648});
this.udPreamp.Name = "udPreamp";
this.udPreamp.Size = new System.Drawing.Size(40, 20);
this.udPreamp.TabIndex = 52;
this.udPreamp.Value = new decimal(new int[] {
0,
0,
0,
0});
this.udPreamp.ValueChanged += new System.EventHandler(this.udPreamp_ValueChanged);
this.udPreamp.LostFocus += new System.EventHandler(this.udPreamp_LostFocus);
//
// groupBox2
//
this.groupBox2.Controls.Add(this.checkBoxRecord);
this.groupBox2.Location = new System.Drawing.Point(320, 8);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(88, 64);
this.groupBox2.TabIndex = 5;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Record";
//
// checkBoxRecord
//
this.checkBoxRecord.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxRecord.Image = null;
this.checkBoxRecord.Location = new System.Drawing.Point(16, 24);
this.checkBoxRecord.Name = "checkBoxRecord";
this.checkBoxRecord.Size = new System.Drawing.Size(56, 24);
this.checkBoxRecord.TabIndex = 0;
this.checkBoxRecord.Text = "Record";
this.checkBoxRecord.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.checkBoxRecord.CheckedChanged += new System.EventHandler(this.checkBoxRecord_CheckedChanged);
//
// grpPlayback
//
this.grpPlayback.Controls.Add(this.txtCurrentFile);
this.grpPlayback.Controls.Add(this.lblCurrentlyPlaying);
this.grpPlayback.Controls.Add(this.btnNext);
this.grpPlayback.Controls.Add(this.btnPrevious);
this.grpPlayback.Controls.Add(this.checkBoxPause);
this.grpPlayback.Controls.Add(this.btnStop);
this.grpPlayback.Controls.Add(this.checkBoxPlay);
this.grpPlayback.Location = new System.Drawing.Point(8, 8);
this.grpPlayback.Name = "grpPlayback";
this.grpPlayback.Size = new System.Drawing.Size(304, 88);
this.grpPlayback.TabIndex = 4;
this.grpPlayback.TabStop = false;
this.grpPlayback.Text = "Playback";
//
// txtCurrentFile
//
this.txtCurrentFile.Location = new System.Drawing.Point(104, 24);
this.txtCurrentFile.Name = "txtCurrentFile";
this.txtCurrentFile.ReadOnly = true;
this.txtCurrentFile.Size = new System.Drawing.Size(184, 20);
this.txtCurrentFile.TabIndex = 9;
//
// lblCurrentlyPlaying
//
this.lblCurrentlyPlaying.Image = null;
this.lblCurrentlyPlaying.Location = new System.Drawing.Point(16, 24);
this.lblCurrentlyPlaying.Name = "lblCurrentlyPlaying";
this.lblCurrentlyPlaying.Size = new System.Drawing.Size(96, 23);
this.lblCurrentlyPlaying.TabIndex = 10;
this.lblCurrentlyPlaying.Text = "Currently Playing:";
//
// btnNext
//
this.btnNext.Enabled = false;
this.btnNext.Image = null;
this.btnNext.Location = new System.Drawing.Point(232, 56);
this.btnNext.Name = "btnNext";
this.btnNext.Size = new System.Drawing.Size(40, 23);
this.btnNext.TabIndex = 8;
this.btnNext.Text = "Next";
this.btnNext.Click += new System.EventHandler(this.btnNext_Click);
//
// btnPrevious
//
this.btnPrevious.Enabled = false;
this.btnPrevious.Image = null;
this.btnPrevious.Location = new System.Drawing.Point(184, 56);
this.btnPrevious.Name = "btnPrevious";
this.btnPrevious.Size = new System.Drawing.Size(40, 23);
this.btnPrevious.TabIndex = 7;
this.btnPrevious.Text = "Prev";
this.btnPrevious.Click += new System.EventHandler(this.btnPrevious_Click);
//
// checkBoxPause
//
this.checkBoxPause.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxPause.Enabled = false;
this.checkBoxPause.Image = null;
this.checkBoxPause.Location = new System.Drawing.Point(128, 56);
this.checkBoxPause.Name = "checkBoxPause";
this.checkBoxPause.Size = new System.Drawing.Size(48, 23);
this.checkBoxPause.TabIndex = 5;
this.checkBoxPause.Text = "Pause";
this.checkBoxPause.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.checkBoxPause.CheckedChanged += new System.EventHandler(this.checkBoxPause_CheckedChanged);
//
// btnStop
//
this.btnStop.Enabled = false;
this.btnStop.Image = null;
this.btnStop.Location = new System.Drawing.Point(32, 56);
this.btnStop.Name = "btnStop";
this.btnStop.Size = new System.Drawing.Size(40, 23);
this.btnStop.TabIndex = 4;
this.btnStop.Text = "Stop";
this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
//
// checkBoxPlay
//
this.checkBoxPlay.Appearance = System.Windows.Forms.Appearance.Button;
this.checkBoxPlay.Enabled = false;
this.checkBoxPlay.Image = null;
this.checkBoxPlay.Location = new System.Drawing.Point(80, 56);
this.checkBoxPlay.Name = "checkBoxPlay";
this.checkBoxPlay.Size = new System.Drawing.Size(40, 23);
this.checkBoxPlay.TabIndex = 3;
this.checkBoxPlay.Text = "Play";
this.checkBoxPlay.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.checkBoxPlay.CheckedChanged += new System.EventHandler(this.checkBoxPlay_CheckedChanged);
//
// chkAlwaysOnTop
//
this.chkAlwaysOnTop.Image = null;
this.chkAlwaysOnTop.Location = new System.Drawing.Point(301, 469);
this.chkAlwaysOnTop.Name = "chkAlwaysOnTop";
this.chkAlwaysOnTop.Size = new System.Drawing.Size(99, 19);
this.chkAlwaysOnTop.TabIndex = 65;
this.chkAlwaysOnTop.Text = "Always On Top";
this.chkAlwaysOnTop.CheckedChanged += new System.EventHandler(this.chkAlwaysOnTop_CheckedChanged);
//
// WaveControl
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(416, 500);
this.Controls.Add(this.chkAlwaysOnTop);
this.Controls.Add(this.checkBoxTS1);
this.Controls.Add(this.groupBoxTS2);
this.Controls.Add(this.chkBoxMP3);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.chkQuickAudioFolder);
this.Controls.Add(this.createBoxTS);
this.Controls.Add(this.TXIDBoxTS);
this.Controls.Add(this.chkQuickPlay);
this.Controls.Add(this.chkQuickRec);
this.Controls.Add(this.groupBoxTS1);
this.Controls.Add(this.grpPlaylist);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.grpPlayback);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Menu = this.mainMenu1;
this.MinimumSize = new System.Drawing.Size(400, 200);
this.Name = "WaveControl";
this.Text = "Wave File Controls";
this.Closing += new System.ComponentModel.CancelEventHandler(this.WaveControl_Closing);
this.grpPlaylist.ResumeLayout(false);
this.groupBoxTS2.ResumeLayout(false);
this.groupBoxTS1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.tbPreamp)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.udPreamp)).EndInit();
this.groupBox2.ResumeLayout(false);
this.grpPlayback.ResumeLayout(false);
this.grpPlayback.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
#region Properties
private int currently_playing;
private int CurrentlyPlaying
{
get { return currently_playing; }
set
{
if(value > lstPlaylist.Items.Count-1)
value = lstPlaylist.Items.Count-1;
currently_playing = value;
if(currently_playing == 0)
btnPrevious.Enabled = false;
else
btnPrevious.Enabled = true;
if(currently_playing == lstPlaylist.Items.Count-1)
{
if(!checkBoxLoop.Checked)
btnNext.Enabled = false;
}
else
btnNext.Enabled = true;
}
}
#endregion
// ke9ns add pass string from console play button right click
private static string QPFile = null;
public static string QPFILE
{
get { return QPFile; }
set { QPFile = value; }
}
//=======================================================
// ke9ns add rec/playid & waterID & scheduler turn on post audio (called from console)
public bool RECPLAY
{
get { return false; }
set
{
WaveOptions.RECPLAY1 = value;
}
} // RECPLAY
//=======================================================
// ke9ns add scheduler reduce file size by SR wav file reduction
public bool RECPLAY2
{
get { return false; }
set
{
quickmp3SR = WaveOptions.comboSampleRate.Text; // save SR value before reducing
WaveOptions.comboSampleRate.Text = "48000"; // reduce file size
}
} // RECPLAY2
// ke9ns add restore original SR back when done with scheduled recording
public bool RECPLAY3
{
get { return false; }
set
{
WaveOptions.radRXPreProcessed.Checked = WaveOptions.temp_record;
WaveOptions.radTXPreProcessed.Checked = WaveOptions.temp_record;
WaveOptions.comboSampleRate.Text = quickmp3SR; // restore file size SR
}
} // RECPLAY3
private static void ConvertMp3ToWav(string _inPath_, string _outPath_)
{
using (Mp3FileReader mp3 = new Mp3FileReader(_inPath_))
{
using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(mp3))
{
// WaveFileWriter.CreateWaveFile(_outPath_, pcm);
}
}
}
#region Misc Routines
//=============================================================================================================
//=============================================================================================================
//ke9ns Check out wave file to see if it is correct for playing
//=============================================================================================================
//=============================================================================================================
public bool OpenWaveFile(string filename, bool rx2)
{
RIFFChunk riff = null;
fmtChunk fmt = null;
dataChunk data_chunk = null;
if(!File.Exists(filename)) // ke9ns check if file name works
{
if (chkQuickAudioFolder.Checked == true)
{
MessageBox.Show("QuickAudio Save Folder Filename doesn't exist. (" + filename + ")\n" +
"Close this message, and Right Click on the Play button, then select a file and Click Open,\n" +
"You most likely renamed a Quickaudio file which caused this. " , "Bad Filename",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else
{
MessageBox.Show("Filename doesn't exist. (" + filename + ")",
"Bad Filename",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
file_list.RemoveAt(currently_playing);
}
return false;
}
BinaryReader reader = null;
try
{
reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read)); // ke9ns see if the file can be opened
}
catch(Exception)
{
MessageBox.Show("File is already open.");
return false;
}
if(reader.BaseStream.Length == 0 || reader.PeekChar() != 'R') // ke9ns see if a RIFF type wave file
{
reader.Close();
MessageBox.Show("File is not in the correct format.",
"Wrong File Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
file_list.RemoveAt(currently_playing);
return false;
}
while( (data_chunk == null || riff == null || fmt == null) && (reader.BaseStream.Position < reader.BaseStream.Length) )
{
Chunk chunk = Chunk.ReadChunk(ref reader);
if(chunk.GetType() == typeof(RIFFChunk))
riff = (RIFFChunk)chunk;
else if(chunk.GetType() == typeof(fmtChunk))
fmt = (fmtChunk)chunk;
else if(chunk.GetType() == typeof(dataChunk))
data_chunk = (dataChunk)chunk;
}
if (reader.BaseStream.Position == reader.BaseStream.Length)
{
reader.Close();
MessageBox.Show("File is not in the correct format.",
"Wrong File Format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
file_list.RemoveAt(currently_playing);
return false;
}
if(riff.riff_type != 0x45564157)
{
reader.Close();
MessageBox.Show("File is not an RIFF Wave file.",
"Wrong file format",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
file_list.RemoveAt(currently_playing);
return false;
}
if (!TXIDBoxTS.Checked) // ke9ns add: dont check if doing a TX ID
{ // format =1 means PCM
if (!CheckSampleRate(fmt.sample_rate) || (fmt.format == 1 && fmt.sample_rate != Audio.SampleRate1)) // ke9ns: needs to be on the list of sample rates BUT needs to match the current SR otherwise it fails
{
reader.Close();
MessageBox.Show("File has the wrong sample rate.> " + fmt.sample_rate + ", " + Audio.SampleRate1,
"Wrong Sample Rate",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
file_list.RemoveAt(currently_playing);
return false;
}
if (fmt.channels != 2) // ke9ns must be stereo
{
reader.Close();
MessageBox.Show("Wave File is not stereo.",
"Wrong Number of Channels",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
file_list.RemoveAt(currently_playing);
return false;
}
// Debug.WriteLine("audio go here"); // here at start of playback
} // do above if not a WatefallID TX
//----------------------------------------------------------------------
// this is where the audio is loaded up into the proper reader.
//----------------------------------------------------------------------
if (!rx2)
{
Audio.wave_file_reader = new WaveFileReader1( // ke9ns RX1 format of RIFF wave file to read
this,
console.BlockSize1,
(int)fmt.format, // use floating point
(int)fmt.sample_rate,
(int)fmt.channels,
ref reader);
}
else
{
Audio.wave_file_reader2 = new WaveFileReader1( // ke9ns RX2 format of RIFF wave file to read
this,
console.BlockSize1,
(int)fmt.format, // use floating point
(int)fmt.sample_rate,
(int)fmt.channels,
ref reader);
}
return true;
} // openwavefile
//=========================================================================================
// ke9ns
private bool CheckSampleRate(int rate)
{
bool retval = false;
switch(rate)
{
case 6000:
case 12000:
case 24000:
case 48000:
case 96000:
case 192000:
retval = true; break;
}
return retval;
}
//================================================================
private void UpdatePlaylist()
{
lstPlaylist.BeginUpdate();
lstPlaylist.Items.Clear();
int index = lstPlaylist.SelectedIndex;
foreach(string s in file_list)
{
int i = s.LastIndexOf("\\")+1;
string file = s.Substring(i, s.IndexOf(".wav")-i);
lstPlaylist.Items.Add(file);
}
if(index < 0 && lstPlaylist.Items.Count > 0)
lstPlaylist.SelectedIndex = 0;
else if(lstPlaylist.Items.Count > index)
lstPlaylist.SelectedIndex = index;
lstPlaylist.EndUpdate();
if(lstPlaylist.Items.Count > 0)
{
checkBoxPlay.Enabled = true;
btnRemove.Enabled = true;
checkBoxLoop.Enabled = true;
}
else
{
checkBoxPlay.Enabled = false;
checkBoxPlay.Checked = false;
btnRemove.Enabled = false;
checkBoxLoop.Enabled = false;
}
if(lstPlaylist.Items.Count > 1)
checkBoxRandom.Enabled = true;
else
checkBoxRandom.Enabled = false;
}
//=========================================================================
//=========================================================================
// ke9ns This is what shuts the audio off when end of wave file reached
//=========================================================================
//=========================================================================
public void Next()
{
if(checkBoxPlay.Checked)
{
if (btnNext.Enabled)
{
btnNext_Click(this, EventArgs.Empty);
}
else if (checkBoxLoop.Checked && lstPlaylist.Items.Count == 1)
{
checkBoxPlay_CheckedChanged(this, EventArgs.Empty);
}
else
{
checkBoxPlay.Checked = false;
}
}
//k6jca added code...
if (chkQuickPlay.Checked) // ke9ns this is false if you ended the PLAY by releasing the MOX yourself
{
chkQuickPlay.Checked = false; // ke9ns only comes here is PLAY finishes on its own
// Debug.WriteLine("here DONE WITH PLAY0");
}
bool temp = console.chkSR.Checked;
console.chkSR.Checked = !console.chkSR.Checked; // ke9ns add
do
{
// wait
Thread.Sleep(100);
} while (temp == console.chkSR.Checked);
//=========================================================================
//ke9ns add comes here when playback has ended
if (TXIDBoxTS.Checked)
{
TXIDBoxTS.Checked = false; // tell Waterfall ID routine to turn off since the wave file is done
}
console.chkSR.Checked = !console.chkSR.Checked; // ke9ns add toggles SR to force the RX audio to work correctly
do
{
// wait
Thread.Sleep(100);
} while (temp != console.chkSR.Checked);
} // next()
#endregion
#region Event Handlers
private void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach(string s in openFileDialog1.FileNames)
{
if(!file_list.Contains(s))
file_list.Add(s);
}
UpdatePlaylist();
}
//=========================================================================================
// ke9ns PLAY button (for playback of standard recordings or IQ recordings
private void checkBoxPlay_CheckedChanged(object sender, System.EventArgs e)
{
if(checkBoxPlay.Checked)
{
string filename = (string)file_list[currently_playing];
if(!OpenWaveFile(filename, false))
{
checkBoxPlay.Checked = false;
currently_playing = -1;
UpdatePlaylist();
return;
}
if ((console.CurrentModel == Model.FLEX5000) && ( FWCEEPROM.RX2OK )&& (console.RX2Enabled))
{
string filename2 = filename+"-rx2";
if(File.Exists(filename2)) OpenWaveFile(filename2, true);
}
txtCurrentFile.Text = (string)lstPlaylist.Items[currently_playing];
checkBoxPlay.BackColor = console.ButtonSelectedColor;
checkBoxPause.Enabled = true;
}
else // if not playing audio
{
if(Audio.wave_file_reader != null) Audio.wave_file_reader.Stop();
if (Audio.wave_file_reader2 != null) Audio.wave_file_reader2.Stop();
Thread.Sleep(50); // wait for files to close
if(checkBoxPause.Checked) checkBoxPause.Checked = false;
checkBoxPause.Enabled = false;
txtCurrentFile.Text = "";
checkBoxPlay.BackColor = SystemColors.Control;
}
Audio.wave_playback = checkBoxPlay.Checked;
console.WavePlayback = checkBoxPlay.Checked;
// Debug.WriteLine("audio done here");
} //checkBoxPlay_CheckedChanged
public static string scheduleName; // ke9ns add for saving file name of recording
public static string scheduleName1; // ke9ns add for saving file name of recording
public static string scheduleName2; // ke9ns add for saving file name of recording
private void checkBoxRecord_CheckedChanged(object sender, System.EventArgs e)
{
if(checkBoxRecord.Checked)
{
string rec_type = "";
int short_sample_rate = 48;
int long_sample_rate = 4800;
checkBoxRecord.BackColor = console.ButtonSelectedColor;
if (Audio.RecordRXPreProcessed)
{
rec_type = " IQ";
long_sample_rate = console.SampleRate1;
short_sample_rate = long_sample_rate / 1000;
}
else
{
long_sample_rate = WaveOptions.SampleRate;
short_sample_rate = long_sample_rate / 1000;
}
string temp = console.RX1DSPMode.ToString()+" ";
temp += console.VFOAFreq.ToString("f6")+"MHz [";
temp += short_sample_rate.ToString() + "k";
temp += rec_type + "] ";
temp += DateTime.Now.ToString();
temp = temp.Replace("/", "-");
temp = temp.Replace(":", " ");
// temp = console.AppDataPath + temp;
temp = wave_folder + "\\" + temp;
scheduleName2 = temp;
scheduleName1 = temp + ".mp3"; // ke9ns add
string file_name = temp + ".wav"; // ke9ns this is the file created
scheduleName = file_name; // ke9ns add
string file_name2 = file_name + "-rx2";
Audio.wave_file_writer = new WaveFileWriter(console.BlockSize1, 2, long_sample_rate, file_name);
if (console.CurrentModel == Model.FLEX5000 && FWCEEPROM.RX2OK && console.RX2Enabled)
Audio.wave_file_writer2 = new WaveFileWriter(console.BlockSize1, 2, long_sample_rate, file_name2);
} // checkbox record
Audio.wave_record = checkBoxRecord.Checked;
if (!checkBoxRecord.Checked)
{
if (console.CurrentModel == Model.FLEX5000 && FWCEEPROM.RX2OK && console.RX2Enabled &&
Audio.wave_file_writer != null && Audio.wave_file_writer2 != null)
{
Thread.Sleep(100);
Audio.wave_file_writer2.Stop();
}
Audio.wave_file_writer.Stop();
checkBoxRecord.BackColor = SystemColors.Control;
//MessageBox.Show("The file has been written to the following location:\n"+file_name);
}
} // checkBoxRecord_CheckedChanged(
private void btnAdd_Click(object sender, System.EventArgs e)
{
openFileDialog1.ShowDialog();
}
private void btnRemove_Click(object sender, System.EventArgs e)
{
if(lstPlaylist.Items.Count == 0 ||
lstPlaylist.SelectedIndices.Count == 0) return;
ArrayList selections = new ArrayList();
foreach(int i in lstPlaylist.SelectedIndices)
{
if(i == currently_playing && checkBoxPlay.Checked)
{
Application.DoEvents();
DialogResult dr = MessageBox.Show(
(string)lstPlaylist.Items[i]+
" is currently playing.\n"+
"Stop playing and remove from Playlist?",
"Stop and Remove?",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if(dr == DialogResult.Yes)
{
selections.Add(i);
checkBoxPlay.Checked = false;
}
}
else
selections.Add(i);
}
selections.Sort();
Application.DoEvents();
for(int i=selections.Count-1; i>=0; i--)
file_list.RemoveAt((int)selections[i]);
UpdatePlaylist();
}
private void checkBoxLoop_CheckedChanged(object sender, System.EventArgs e)
{
if(checkBoxLoop.Checked)
checkBoxLoop.BackColor = console.ButtonSelectedColor;
else
checkBoxLoop.BackColor = SystemColors.Control;
}
private void btnStop_Click(object sender, System.EventArgs e)
{
checkBoxPlay.Checked = false;
}
private void checkBoxRandom_CheckedChanged(object sender, System.EventArgs e)
{
if(checkBoxRandom.Checked)
checkBoxRandom.BackColor = console.ButtonSelectedColor;
else
checkBoxRandom.BackColor = SystemColors.Control;
}
private void lstPlaylist_SelectedIndexChanged(object sender, System.EventArgs e)
{
if(lstPlaylist.SelectedIndex < 0)
{
btnPrevious.Enabled = false;
btnNext.Enabled = false;
return;
}
if(!checkBoxPlay.Checked)
{
CurrentlyPlaying = lstPlaylist.SelectedIndex;
}
}
private void btnPrevious_Click(object sender, System.EventArgs e)
{
if(checkBoxPlay.Checked)
{
checkBoxPlay.Checked = false;
CurrentlyPlaying--;
checkBoxPlay.Checked = true;
}
else
lstPlaylist.SelectedIndex--;
}
private void btnNext_Click(object sender, System.EventArgs e)
{
if(checkBoxPlay.Checked)
{
checkBoxPlay.Checked = false;
if(CurrentlyPlaying == lstPlaylist.Items.Count-1)
{
CurrentlyPlaying = 0;
}
else CurrentlyPlaying++;
checkBoxPlay.Checked = true;
}
else
{
int temp = lstPlaylist.SelectedIndex+1;
if(temp == lstPlaylist.Items.Count) temp = 0;
lstPlaylist.SelectedIndex = -1;
lstPlaylist.SelectedIndex = temp;
}
}
private void WaveControl_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
Common.SaveForm(this, "WaveOptions");
}
private void checkBoxPause_CheckedChanged(object sender, System.EventArgs e)
{
if(checkBoxPlay.Checked)
Audio.wave_playback = !checkBoxPause.Checked;
if(checkBoxPause.Checked)
checkBoxPause.BackColor = console.ButtonSelectedColor;
else
checkBoxPause.BackColor = SystemColors.Control;
}
private void lstPlaylist_DoubleClick(object sender, System.EventArgs e)
{
if(checkBoxPlay.Checked)
{
CurrentlyPlaying = lstPlaylist.SelectedIndex;
checkBoxPlay.Checked = false;
checkBoxPlay.Checked = true;
}
else checkBoxPlay.Checked = true;
}
private void mnuWaveOptions_Click(object sender, System.EventArgs e)
{
if(WaveOptions == null || WaveOptions.IsDisposed)
WaveOptions = new WaveOptions();
WaveOptions.Show();
WaveOptions.Focus();
}
private void udPreamp_ValueChanged(object sender, System.EventArgs e)
{
tbPreamp.Value = (int)udPreamp.Value;
Audio.WavePreamp = Math.Pow(10.0, (int)udPreamp.Value/20.0); // convert to scalar
}
private void udPreamp_LostFocus(object sender, System.EventArgs e)
{
udPreamp_ValueChanged(sender, e);
}
private void tbPreamp_Scroll(object sender, System.EventArgs e)
{
udPreamp.Value = (decimal)tbPreamp.Value;
}
#endregion
//k6jca
//
// Add two buttons for quick record & play without worrying about
// all of the other stuff...
//
// Note that these routines automatically set the TX/RX Pre/Post variables
// to the proper value for recording off the air (and playing back over the air)
// and then return these back to their original values at the end of the invocation
// of these functions.
//
// Also - turn off TX EQ (during playback) so that this doesn't modify
// the playback audio.
//
// Record & Playback are always to the same file: SDRQuickAudio.wav
//
private bool temp_record = false;
private bool temp_play = false;
private bool temp_mon = false;
private byte temp_pre = 0; // ke9ns add for quickplay function
private bool temp_txeq = false;
private bool temp_cpdr = false;
private bool temp_dx = false;
private bool temp_dexp = false; // dexp
public static int QAC = 0; // ke9ns add
//==================================================================================
// ke9ns mod needed since MON now toggle pre and post audio. quickplay should always be post
private void chkQuickPlay_CheckedChanged(object sender, System.EventArgs e)
{
Debug.WriteLine("WAVE: chkQuickPlay checkchanged");
string file_name;
if (chkQuickAudioFolder.Checked == true) // ke9ns add to allow subfolder with different names to play
{
System.IO.Directory.CreateDirectory(console.AppDataPath + "QuickAudio"); // ke9ns create sub directory
if (console.TIMETOID == true) // ke9ns add
{
console.TIMETOID = false; // reset ID
file_name = console.AppDataPath + "QuickAudio" + "\\IDTIMER.wav"; // ke9ns
}
else if (console.TIMETOID1 == true) // ke9ns add
{
console.TIMETOID1 = false; // reset ID
file_name = console.AppDataPath + "QuickAudio" + "\\IDTIMERCW.wav"; // ke9ns
}
else if (console.CQCQCALL == true) // ke9ns add
{
console.CQCQCALL = false; // reset ID
file_name = console.AppDataPath + "QuickAudio" + "\\CQCQ.wav"; // ke9ns
}
else if (console.CALLCALL == true) // ke9ns add
{
console.CALLCALL = false; // reset ID
// console.checkBoxID.Checked = false;
file_name = console.AppDataPath + "QuickAudio" + "\\CALL.wav"; // ke9ns
}
else if (QPFile != null)
{
file_name = QPFile; // ke9ns check file name passed from console play button
}
else if ((chkQuickPlay.Checked) && QAC > 0)
{
// ke9ns add to keep a missing file name from crashing powersdr
try
{
// file_name = console.AppDataPath + "QuickAudio" + "\\SDRQuickAudio" + QAC.ToString() + QAName() + ".wav";
string[] files = Directory.GetFiles(console.AppDataPath + "QuickAudio" + "\\", "SDRQuickAudio" + QAC.ToString() + "*.wav"); // ke9ns ignore extra part of name
file_name = files[0];
}
catch(Exception )
{
console.ckQuickPlay.Checked = false; // if not transmitting then dont do anything and return.
if (!Directory.Exists(console.AppDataPath)) // need to see the quickaudio folder
{
MessageBox.Show(new Form() { TopMost = true }, "WAVE: could not Find QuickAudio folder. " + console.AppDataPath);
return;
}
else
{
// MessageBox.Show(new Form() { TopMost = true }, "WAVE: could not Find file " + QAC.ToString() + " in QuickAudio folder");
MessageBox.Show(new Form() { TopMost = true }, "WAVE: could not Find file " + QAC.ToString() + " in QuickAudio folder");
return;
}
}
} // else
else
{
file_name = console.AppDataPath + "SDRQuickAudio.wav";
console.ckQuickPlay.Checked = false; // if not transmitting then dont do anything and return.
}
} // quickqudiofolder enabled
else
{
file_name = console.AppDataPath + "SDRQuickAudio.wav";
}
//--------------------------------------------------------------------
if (chkQuickPlay.Checked == true)
{
if (Directory.Exists(console.AppDataPath)) // need to see the quickaudio folder
{
if (File.Exists(file_name))
{
Debug.WriteLine("found file name " + file_name);
}
else
{
console.ckQuickPlay.Checked = false; // if not transmitting then dont do anything and return.
MessageBox.Show(new Form() { TopMost = true }, "Wave: Could not Find file: " + file_name + " in QuickAudio folder");
return;
}
}
else
{
console.ckQuickPlay.Checked = false; // if not transmitting then dont do anything and return.
MessageBox.Show(new Form() { TopMost = true }, "Wave: could not Find QuickAudio folder.. "+ console.AppDataPath);
return;
}
}
//----------------------------------------------------------------------------------
if (chkQuickPlay.Checked) // do at the start of playing audio file
{
temp_txeq = console.TXEQ;
console.TXEQ = false; // set TX Eq temporarily to OFF
temp_cpdr = console.CPDR;
console.CPDR = false;
temp_dx = console.DX;
console.DX = false;
temp_dexp = console.DEXP; // ke9ns add: disable DEXP during quickplay.
console.DEXP = false;
temp_play = Audio.RecordTXPreProcessed;
Audio.RecordTXPreProcessed = true; // set TRUE temporarily
// temp_pre = Audio.MON_PRE; // ke9ns add
temp_mon = console.MON; // record original MON setting
#if NO_MON
if (console.RX1DSPMode == DSPMode.AM || console.RX1DSPMode == DSPMode.FM || console.RX1DSPMode == DSPMode.SAM)
{
console.MON = false;
}
else
{
console.MON = true;
}
#else
if (temp_mon == false) // if original MON was OFF
{
Audio.MON_PRE = 0;
console.MONINIT = 1; // ke9ns add
console.MON = true; // turn post MON on
// Debug.WriteLine("1mon == false");
}
else
{
// console.MONINIT = 1;
// console.MON = true;
}
#endif
if (!OpenWaveFile(file_name, false))
{
chkQuickPlay.Checked = false;
Audio.MON_PRE = temp_pre; // ke9ns add
if (temp_mon == false)
{
Audio.MON_PRE = 0;
console.MONINIT = 1;
console.MON = temp_mon;// turn off MON
}
else
{
// just leave it alone
}
Audio.RecordTXPreProcessed = temp_play; //return to original state
console.TXEQ = temp_txeq; // set TX Eq back to original state
return;
}
/*if (console.CurrentModel == Model.FLEX5000 && FWCEEPROM.RX2OK && console.RX2Enabled)
{
string file_name2 = file_name+"-rx2";
OpenWaveFile(file_name2, true);
}*/
chkQuickPlay.BackColor = console.ButtonSelectedColor;
} // quickplay checked and playing audio
else // quickplay DONE, over, finished
{
if (Audio.wave_file_reader != null) Audio.wave_file_reader.Stop();
/*if (Audio.wave_file_reader2 != null)
Audio.wave_file_reader2.Stop();*/
chkQuickPlay.BackColor = SystemColors.Control;
console.QuickPlay = false;
if (temp_mon == false)
{
Audio.MON_PRE = 0;
console.MONINIT = 1;
console.MON = false;// turn off MON
// Debug.WriteLine("mon == false");
}
else
{
// just leave it alone
}
Audio.RecordTXPreProcessed = temp_play; //return to original state
console.TXEQ = temp_txeq; // set TX Eq back to original state
console.CPDR = temp_cpdr;
console.DX = temp_dx;
console.DEXP = temp_dexp; // ke9ns add
console.checkBoxID.Checked = false; // ke9ns add
console.buttonCQ.BackColor = Color.Blue; // ke9ns add
console.buttonCall.BackColor = Color.Blue; // kens add
}
Audio.wave_playback = chkQuickPlay.Checked; // PLAY AUDIO FILE HERE
console.WavePlayback = chkQuickPlay.Checked;
}// chkQuickPlay changed
public static string quickmp3SR; // ke9ns add
public static string quickmp3; // ke9ns add
//============================================================================================
private void chkQuickRec_CheckedChanged(object sender, System.EventArgs e)
{
if(chkQuickRec.Checked)
{
temp_record = Audio.RecordRXPreProcessed;
quickmp3SR = WaveOptions.comboSampleRate.Text;
if (chkBoxMP3.Checked == true)
WaveOptions.comboSampleRate.Text = "48000"; // reduce file size
Audio.RecordRXPreProcessed = false; //ke9ns add set this FALSE temporarily
chkQuickRec.BackColor = console.ButtonSelectedColor;
chkQuickPlay.Enabled = true;
string file_name;
if (chkQuickAudioFolder.Checked == true)
{
QAC++;
System.IO.Directory.CreateDirectory(console.AppDataPath + "QuickAudio"); // ke9ns add create sub directory
System.IO.Directory.CreateDirectory(console.AppDataPath + "QuickAudioMP3"); // ke9ns add create sub directory
file_name = console.AppDataPath + "QuickAudio"+ "\\SDRQuickAudio" + QAC.ToString() + QAName() + ".wav";
quickmp3 = console.AppDataPath + "QuickAudioMP3" + "\\SDRQuickAudio" + QAC.ToString() + QAName() +".mp3"; // ke9ns add mp3
// Debug.WriteLine("qac" + QAC);
}
else // ke9ns old way quickaudio
{
file_name = console.AppDataPath + "SDRQuickAudio.wav";
quickmp3 = console.AppDataPath + "SDRQuickAudio.mp3"; // ke9ns add mp3
}
Audio.wave_file_writer = new WaveFileWriter(console.BlockSize1, 2, WaveOptions.SampleRate, file_name);
/*if (console.CurrentModel == Model.FLEX5000 && FWCEEPROM.RX2OK && console.RX2Enabled)
{
string file_name2 = file_name + "-rx2";
Audio.wave_file_writer2 = new WaveFileWriter(console.BlockSize1, 2, waveOptionsForm.SampleRate, file_name2);
}*/
} //chkQuickRec.checked
Audio.wave_record = chkQuickRec.Checked;
if (!chkQuickRec.Checked)
{
/*if (console.CurrentModel == Model.FLEX5000 && FWCEEPROM.RX2OK && console.RX2Enabled && Audio.wave_file_writer2 != null)
{
Thread.Sleep(100);
Audio.wave_file_writer2.Stop();
}*/
string file_name = Audio.wave_file_writer.Stop();
chkQuickRec.BackColor = SystemColors.Control;
if (console.checkBoxID.Checked == false) // ke9ns add
{
MessageBox.Show("The 'Over the Air' Quick audio recording has been successfully created.\n" +
"Key the radio with either PTT or MOX and click on the Play button to play back the Quick audio recording over the air.");
// MessageBox.Show("The file has been written to the following location:\n"+file_name);
}
Audio.RecordRXPreProcessed = temp_record; //return to original state
WaveOptions.comboSampleRate.Text = quickmp3SR; // restore file size
//---------------------------------------------------------
// ke9ns add save an MP3 to go along with the WAV file (NAudio.Lame)
if (chkBoxMP3.Checked == true)
{
try
{
using (var reader = new WaveFileReader(file_name)) // closes reader when done using
using (var writer = new LameMP3FileWriter(quickmp3, reader.WaveFormat, LAMEPreset.VBR_90)) // closes writer when done using (90=90% quality variable bit rate)
{
reader.CopyTo(writer); // create MP3 file
}
}
catch (Exception)
{
}
Debug.WriteLine("DONE WITH MP3 CREATION" + quickmp3);
}
} // if (!chkQuickRec.Checked)
} // chkQuickRec_CheckedChanged
public bool QuickRec
{
get { return chkQuickRec.Checked; }
set { chkQuickRec.Checked = value; }
}
public bool QuickPlay
{
get
{
return chkQuickPlay.Checked;
}
set
{
chkQuickPlay.Checked = value;
}
}
//=========================================================================
public bool TXIDPlay // ke9ns ADD for TX waterfall ID
{
get { return TXIDBoxTS.Checked; }
set
{
TXIDBoxTS.Checked = value;
}
}
//=========================================================================================
//=========================================================================================
//=========================================================================================
// ke9ns add: Play waterfall ID wave file here (below createBoxTS creates the wave file)
//=========================================================================================
//=========================================================================================
//=========================================================================================
public int samplesPerSecondL = 0;
private void TXIDBoxTS_CheckedChanged(object sender, EventArgs e) // ke9ns ADD TX waterfall ID
{
string file_name = console.AppDataPath + "ke9ns.wav"; // TEXT to waterfall image only
//=========================================================================================
// Determine if Sending Waterfall or not
//=========================================================================================
if (TXIDBoxTS.Checked)
{
// the wave file will have been created if the callsign text box is green. The code should prevent you coming here if its not green.
//=========================================================================================
//=========================================================================================
//=========================================================================================
// Send Digital PCM to QuickPlay Audio stream
//=========================================================================================
//=========================================================================================
//=========================================================================================
console.TXIDMenuItem.Text = "Transmit";
//-------------------------------------------------------------------------------
// play ke9ns.wav file here
//-------------------------------------------------------------------------------
temp_txeq = console.TXEQ;
console.TXEQ = false; // set TX Eq temporarily to OFF
temp_cpdr = console.CPDR;
console.CPDR = false;
temp_dx = console.DX;
console.DX = false;
temp_play = Audio.RecordTXPreProcessed;
Audio.RecordTXPreProcessed = true; // set TRUE temporarily
temp_mon = console.MON;
// console.MON = false;
Debug.WriteLine("playing ");
if (!OpenWaveFile(file_name, false))
{
TXIDBoxTS.Checked = false;
console.TXIDMenuItem.Checked = false;
console.chkMOX.Checked = false;
console.MON = temp_mon;
Audio.RecordTXPreProcessed = temp_play; //return to original state
console.TXEQ = temp_txeq; // set TX Eq back to original state
return;
}
TXIDBoxTS.BackColor = console.ButtonSelectedColor;
} // txidboxts checked
else// this is what signals the end of playback
{
if (Audio.wave_file_reader != null) Audio.wave_file_reader.Stop();
TXIDBoxTS.BackColor = SystemColors.Control;
Debug.WriteLine("DONE playing ");
console.MON = temp_mon;
Audio.RecordTXPreProcessed = temp_play; //return to original state
console.TXEQ = temp_txeq; // set TX Eq back to original state
console.CPDR = temp_cpdr;
console.DX = temp_dx;
console.TXIDMenuItem.Checked = false; // turn off TX waterfall ID here
} // txidboxts not checked
Audio.wave_playback = TXIDBoxTS.Checked; // this trigger audio.cs to play audio this is read in console.cs
console.WavePlayback = TXIDBoxTS.Checked; // this triggers the audio playback
} // TXIDBoxTS checkchanged
//=========================================================================
public bool CreatePlay // ke9ns ADD for TX waterfall ID (comes from console.callsignTextBox)
{
get { return createBoxTS.Checked; }
set
{
createBoxTS.Checked = value;
}
}
//=========================================================================================
//=========================================================================================
//=========================================================================================
// ke9ns ADD this routine creates the waterfall ID (txidBoxTS plays it)
// when mouse moved in/out a thread routine starts which converts image to wav
//=========================================================================================
//=========================================================================================
//=========================================================================================
public DSPMode BandL = 0;
public int TxfhL = 0;
private void createBoxTS_CheckedChanged(object sender, EventArgs e)
{
if (createBoxTS.Checked)
{
// Debug.WriteLine("check create");
if ((console.Callsign != console.LastCall) || (console.RX1DSPMode != BandL) || ((console.WIDEWATERID == true) && (console.TXFilterHigh != TxfhL)) ) // check if we need to create a new wave file or use the old one.
{
TxfhL = console.TXFilterHigh;
Thread t = new Thread(new ThreadStart(CreateWaterfallID));
t.Name = "Create Waterfall ID wave file Thread";
t.IsBackground = true;
t.Priority = ThreadPriority.Normal;
t.Start();
} // console.Callsign != console.LastCall) || (console.RX1DSPMode != BandL))
else
{
console.callsignTextBox.BackColor = Color.MediumSpringGreen; // green if your last callsign is still a valid wave
console.menuStrip1.Invalidate();
console.menuStrip1.Update();
createBoxTS.Checked = false; // do only 1 time
}
} // createBoxTS.Checked)
}// createBoxTS_CheckedChanged
//============================================================================================
//============================================================================================
// ke9ns add THREAD process to create wave file from text or bitmap image here (TXWaterID)
//============================================================================================
//============================================================================================
private void CreateWaterfallID()
{
string file_name = console.AppDataPath + "ke9ns.wav"; // TEXT to waterfall image only 16bit 48khz SR, 768 kbps
string file_name1 = console.AppDataPath + "ke9ns.bmp"; // image file to waterfall
console.callsignTextBox.BackColor = Color.PaleVioletRed; // let user know your creating a new wave file
console.menuStrip1.Invalidate();
console.menuStrip1.Update();
console.LastCall = console.Callsign; // check if changed callsign, mode, or sample rate
samplesPerSecondL = console.SampleRate1;
BandL = console.RX1DSPMode;
int IMAGE = 0; // 0=text, 1=image
// t.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
// t.CurrentUICulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
int xm = 100; // width was 100
if (console.Callsign.EndsWith(".") == true)
{
IMAGE = 1; // get real image file
file_name1 = console.AppDataPath + console.Callsign + "bmp"; // image file to waterfall
xm = 200; // was 100
}
double bright = 500; // ke9ns volume level (was 400 amplitude factor_
int n1 = 0; // used by USB/LSB routine
int n2 = 0;
int n3 = 0;
int n4 = 0;
SizeF cl = new SizeF(); // determine left or right side of bitmap
int fontS = 34; // was 12
int ym = 40; // height was 22
if (IMAGE == 0)
{
ym = 26; // was 22
}
long xm4 = 4 * ((xm + 3) / 4);
const float bw = .114F; // factors to convert RGB color to grayscale
const float gw = .587F;
const float rw = .2989F;
byte[,] ap = new byte[xm + 10, ym + 10]; // get bitmap data
//=========================================================================================
//=========================================================================================
// Choose TEXT or BITMAP txwaterid
//=========================================================================================
//=========================================================================================
if (IMAGE == 0) // text = 0
{
//=========================================================================================
// 24bit TEXT Bitmap Generate and SCAN
//=========================================================================================
ke9ns_bmp = new Bitmap(xm, ym, PixelFormat.Format24bppRgb); // initialize bitmap for call sign insertion
Graphics g1 = Graphics.FromImage(ke9ns_bmp);
g1.SmoothingMode = SmoothingMode.AntiAlias;
g1.InterpolationMode = InterpolationMode.HighQualityBicubic;
g1.PixelOffsetMode = PixelOffsetMode.HighQuality;
// Pen p = new Pen(Color.AntiqueWhite, 1); // pen color white
// g1.DrawRectangle(p, 1, 4, xm - 1, ym - 4); // draw box
n4 = 0; // USB
string temp1A = console.Callsign;
int temp2 = console.Callsign.Length;
if (temp2 < 8) //if the callsign text is less then 7 char, then add space between each character to make it more legible
{
temp1A = "";
for (int z = 0; z < temp2; z++)
{
temp1A = temp1A + console.Callsign.Substring(z, 1);
if (z != (temp2 - 1)) temp1A = temp1A + " ";
}
}
Debug.WriteLine("CALLSIGN [" + temp1A + "]");
do
{
cl = g1.MeasureString(temp1A, new Font("Arial", fontS, FontStyle.Regular)); // temp used to determine the size of the string when in LSB and you need to reserve a certain space
fontS--;
} while ((cl.Width > 100) && (fontS > 9)); // 89 ke9ns reduce size of font until the string fits into bandpass
Debug.WriteLine("MEASUREMENT LENGTH "+ cl + " , " + fontS + " , "+ xm);
// ke9ns cl = 89 is max width in pixels
// cl = g1.MeasureString(console.Callsign, new Font("Arial", fontS,FontStyle.Regular)); // temp used to determine the size of the string when in LSB and you need to reserve a certain space
// cl = g1.MeasureString(console.Callsign, new Font(SystemFonts.DefaultFont,FontStyle.Regular)); // temp used to determine the size of the string when in LSB and you need to reserve a certain space
cl.Width = (xm / 2) - (cl.Width / 2);
cl.Height = (ym / 2) - (cl.Height / 2) + 2;
//===========================================================================================
// find if USB or LSB on RX1 or RX2 ?
if (console.chkVFOATX.Checked == true)
{
if (console.RX1DSPMode == DSPMode.LSB) n4 = 1;
}
else // not vfoa
{
if (console.RX2DSPMode == DSPMode.LSB) n4 = 1; // for (int n = 1; n != xm; n=n+1) // displays right to left (LSB)
} // vfoA
// new Font("Arial", fontS),
g1.DrawString(temp1A, new Font("Arial", fontS,FontStyle.Regular), Brushes.White, cl.Width, cl.Height); // determine USB or LSB, then draw callsign into bitmap
// g1.DrawString(console.Callsign, new Font(SystemFonts.DefaultFont,FontStyle.Regular), Brushes.AntiqueWhite, cl.Width, cl.Height); // determine USB or LSB, then draw callsign into bitmap
g1.Flush(); // done with graphic function
//=======================================================================
// CONVERT BITMAP into ARRAY of float values for brightness x,y
// ap[,] = vales between 0 and 1 (0=dark, 255=white)
for (int y = ym - 1; y >= 0; y--) // image is saved in correct direction
{
for (int n = 0; n != xm; n++) //
{
Color pixel = ke9ns_bmp.GetPixel(n, y); // bitmap is correct x direction but y is backwards
float temp1 = (((bw * (float)pixel.B) + (gw * (float)pixel.G) + (rw * (float)pixel.R)));
byte temp = (byte)(temp1 * 0.6);
// look at picture data and pick color based on index value found, AND invert so white = BLACK (no signal) , white = full signal (thats the 255- part)
// the /255 is to convert down to a
if (n4 == 0) // USB
{
ap[n, ym - y - 1] = temp;
}
else // LSB
{
ap[xm - n, ym - y - 1] = temp;
}
} // n
} // Y
ke9ns_bmp.Dispose(); // text image
g1.Dispose();
//===========================================================================================
// end TEXT BITMAP 24bit
} // IMAGE 0=text here
else
{
//=========================================================================================
// Get 24bit or 8bpp Bitmap Image loaded up
//=========================================================================================
if (!File.Exists(file_name1))
{
MessageBox.Show("Filename doesn't exist. (" + file_name1 + ")",
"Bad Filename",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
TXIDBoxTS.Checked = false;
console.TXIDMenuItem.Checked = false; // turn off TX waterfall ID here
createBoxTS.Checked = false; // do only 1 time
return;
}
FileStream stream1 = new FileStream(file_name1, FileMode.Open); // open BMP file
BinaryReader reader = new BinaryReader(stream1);
reader.ReadChars(10); // ignore BM characters to start bitmap header
long hrdlen = reader.ReadInt32(); // offset in bitmap to first byte of image data
reader.ReadChars(4); // header size ignore
long xm1 = reader.ReadInt32(); // width in pixels
long ym1 = reader.ReadInt32(); // height in pixels
reader.ReadBytes(2); // color plane assumed to be 1
int bpp = reader.ReadInt16(); // reader.ReadBytes(2); // bpp assumed to be 8bpp
reader.ReadBytes(24); // ignore rest of header to get to color values (255 in 8bpp set)
xm = (int)xm1; // convert to xm
ym = (int)ym1; // convert to ym
int color24 = 1;
if (bpp == 24) color24 = 1;
else color24 = 0;
//=========================================================================================
// 24 bit color Image bitmap scan
//=========================================================================================
if (color24 == 1) // 24bpp color grayscale (no color index needed)
{
xm4 = xm;
ap = new Byte[xm + 10, ym + 10]; // convert to grayscale
//===========================================================================================
// find if USB or LSB on RX1 or RX2 ?
n4 = 0; // USB
if (console.chkVFOATX.Checked == true)
{
if (console.RX1DSPMode == DSPMode.LSB) n4 = 1;
}
else // not vfoa
{
if (console.RX2DSPMode == DSPMode.LSB) n4 = 1;
} // vfoA
//=============================================================================================
// convert bitmap into grayscale bitmap corrected for sending
// ap[,] = vales between 0 and 1 (0=dark, 255=white)
for (int y = 0; y < ym; y++) // image is saved in correct direction
{
for (int n = 0; n != xm; n++) //
{
// look at picture data and pick color based on index value found, AND invert so white = BLACK (no signal) , white = full signal (thats the 255- part)
// the /255 is to convert down to a
float temp1 = ((bw * (float)reader.ReadByte()) + (gw * (float)reader.ReadByte()) + (rw * (float)reader.ReadByte()));
byte temp = (byte)(temp1 * 0.45); // reduce overall max value to prevent overdriving sine waves
if (n4 == 0) // USB
{
ap[n, y] = (byte)(114 - temp);
if (ap[n, y] < 10) ap[n, y] = 0;
}
else // LSB
{
ap[xm - n, y] = (byte)(114 - temp);
if (ap[xm - n, y] < 10) ap[xm - n, y] = 0;
}
} // X
} // Y
} // color24 ==1
//=========================================================================================
// 256 color 8bpp Image bitmap scan
//=========================================================================================
else // 8bpp 256 color grayscale
{
byte[] col = new Byte[255 + 1]; // color map
xm4 = 4 * ((xm + 3) / 4);
byte[] ri = new byte[xm4 + 1];
ap = new byte[xm4 + 10, ym + 10]; // get bitmap data
// ap1 = new float[xm4 + 10, ym + 10]; // convert to grayscale
// color mapping
for (int n = 0; n < 256; n++)
{
col[n] = (byte)((bw * (float)reader.ReadByte()) + (gw * (float)reader.ReadByte()) + (rw * (float)reader.ReadByte()));
reader.ReadByte(); // ignore 4th byte
}
//===========================================================================================
// find if USB or LSB on RX1 or RX2 ?
if (console.chkVFOATX.Checked == true)
{
if (console.RX1DSPMode == DSPMode.LSB)
{
n1 = 1;
n2 = xm;
n3 = 1;
n4 = 1;
}
else
{
n2 = 0;
n1 = xm;
n3 = -1;
n4 = 0; // USB must flip around here
}
}
else // not vfoa
{
if (console.RX2DSPMode == DSPMode.LSB) // for (int n = 1; n != xm; n=n+1) // displays right to left (LSB)
{
n1 = 1;
n2 = xm;
n3 = 1;
n4 = 1;
}
else // for (int n = (int)xm; n != 0; n--) // displays correctly left to right (USB)
{
n2 = 0;
n1 = xm;
n3 = -1;
n4 = 0; // USB must flip around here
}
} // vfoA
//=============================================================================================
// convert bitmap into grayscale bitmap corrected for sending
// float ap[,] = vales between 0 and 1 (0=dark, 255=white)
for (int y = 0; y < ym; y++) // image is saved in correct direction
{
ri = reader.ReadBytes((int)xm4); // get entire line of bitmap X
for (int n = n1; n != n2; n = n + n3) //
{
// look at picture data and pick color based on index value found, AND invert so white = BLACK (no signal), white = full signal
if (n4 == 0) // USB
{
ap[n1 - n, y] = (byte)((byte)255 - col[ri[xm - n]]); // flip
if (ap[n1 - n, y] < 5) ap[n1 - n, y] = 0;
}
else // LSB
{
ap[n, y] = (byte)((byte)255 - col[ri[xm - n]]); // dont flip
if (ap[n, y] < 5) ap[n, y] = 0;
}
} // X
} // Y
} // color24 == 0 8bpp
reader.Close(); // close wav file
stream1.Close(); // close stream
//===============================================================================
// end IMAGE bitmap
} // IMAGE == 1 image file
//=========================================================================================
// Digital PCM setup and file creation
//=========================================================================================
FileStream stream = new FileStream(file_name, FileMode.Create); // create a wav file
BinaryWriter writer = new BinaryWriter(stream); // create a stream to write to the wav file
//=================================================
// .wav header
const int RIFF = 0x46464952; // 0x46464952 (0x52494646 big-endian form).
const int WAVE = 0x45564157; // 0x45564157 (0x57415645 big-endian form).
const int formatChunkSize = 16; // 16
const int headerSize = 8; // 8
const int format = 0x20746D66; // 0x20746D66 0x666d7420
const short formatType = 1; // 1 PCM
const short tracks = 1; // 1 Stereo = 2
const int samplesPerSecond = 48000; // console.SampleRate1; (fixed flex routine to resample audio to correct SR)
const short bitsPerSample = 16; // 16
short frameSize = (short)(tracks * ((bitsPerSample + 7) / 8)); // tracks 2.875 @ 8000 sps
int bytesPerSecond = samplesPerSecond * frameSize; // 23000 bytes per second
int waveSize = ym;
const int lowtx = 150;
int bandpass = 2400;
if (console.WIDEWATERID == true)
{
if (console.TXFilterHigh > 2400) bandpass = (console.TXFilterHigh - 150);
else bandpass = 2400;
}
else
{
bandpass = 2400;
}
int t2 = 2; // divide the time for each line (this controls how long each line takes)
if (IMAGE == 1)
{
float t3 = ((float)xm / (float)ym); // picture ratio to maintain in waterfall (80w x 80h = 1) (200w x 150h = 1.33) (80w x 20h = 4)
// float t4 = ((float)bandpass / (float)xm); // number of freqs in width of images (200w = 13hz per pixel)longer time .076pix/hz, (80w= 30hz per pixel)shorter time.033pix/hz
t2 = (int)((float)xm * 2 / 20 / (t3+ 1)); // t2 small means long vertical , t2 big means short (20 is max)
if (t2 > 20) t2 = 20;
}
int data = 0x61746164; // (0x64617461 big-endian form).
int samples = (samplesPerSecond * 2) * waveSize / t2; // file size //88200 * 4 = 352800
int dataChunkSize = samples * frameSize / 2; // 46000
int fileSize = (waveSize) + headerSize + formatChunkSize + headerSize + dataChunkSize;
writer.Write(RIFF); // write header to file
writer.Write(fileSize);
writer.Write(WAVE);
writer.Write(format);
writer.Write(formatChunkSize);
writer.Write(formatType);
writer.Write(tracks);
writer.Write(samplesPerSecond);
writer.Write(bytesPerSecond);
writer.Write(frameSize);
writer.Write(bitsPerSample);
writer.Write(data);
writer.Write(dataChunkSize);
//==============================================================
// used if you want the waterfall to be as wide as your transmission bandpass
// int lowtx = console.TXFilterLow;
// int hightx = console.TXFilterHigh;
// int tottx = hightx - lowtx; // band width
// xm = 80 pixels wide
int hzperpixel = (int)(((float)bandpass / (float)xm ) + .5); // 2khz wide = 25hz/pix 6000 = 75 hz per pixel
// Debug.WriteLine("hzperpixel " + hzperpixel);
int sample2 = samplesPerSecond / t2; // samples2 = the amount of time spent on each y1 line
// ap[,] = vales between 0 and 1 (0=dark, 255=white)
bright = bright / (float)xm; // correct brightness level of PCM audio by how many freq points go into each pass
//=========================================================================================
// Create Digital PCM Stream
//=========================================================================================
bool firstdata = false; // true = value other than 0
firstdata = false;
int filesizewav = 0;
int firstzero = 0;
int lastzero = 0;
List<short> s1 = new List<short>(); // (ym*sample2);
for (int y1 = 0; y1 < ym; y1++) // each line (bottom of bitmap is first line out)
{
for (int n = 0; n < sample2; n++) // (generate tone)
{
double t = (double)n / (double)(samplesPerSecond * 2); // used to generate a tone
double temp7 = 0.0;
int i = 0;
//===========================================================
// depending on width of bitmap, display within 150 hz to 2550hz
for (float freq = lowtx; freq < (bandpass + lowtx); freq = freq + hzperpixel,i++) // add up all the frequencies from each line(row) of the bitmap into 1 signal
{
if (ap[i, y1] > 1)
{
temp7 = temp7 + ((double)ap[i, y1] * (Math.Sin(t * (double)freq * 2.0 * Math.PI) ) ); // generate individual tone
}
} // freq loop
//============================================================
short s = (short)(temp7 * bright);
if ((firstdata == false))
{
if (s != 0) firstdata = true; // ke9ns: .139 remove the starting dead space from the transmission
else firstzero++; // count how many 16bit words until the first real data (non-zero)
}
// writer.Write(s); // left 16bits
s1.Add(s); // ke9ns: store wav in array so you can drop the dead space and the start and end of the file
if ((firstdata == true))
{
if (s == 0) lastzero++; // counts how many zeros before the end of the file
}
else
{
lastzero = 0;
}
} // n X 1 line at a time
} // Y
Debug.WriteLine("WAVE=== First zero: " + firstzero + " , Last Zero: " + lastzero + " Arry size: " + s1.Count);
filesizewav = s1.Count;
if (IMAGE == 0)
{
if (lastzero > 40000) // ke9ns: .146 remove end of file
{
lastzero = lastzero - 40000;
filesizewav = s1.Count - lastzero; // remove zeros at end of file
}
}
if (firstzero > 30000) firstzero = firstzero - 30000;
else firstzero = 0;
Debug.WriteLine("1WAVE=== First zero: " + firstzero + " , Last Zero: " + lastzero + " Arry size: " + s1.Count);
for (int q = firstzero; q < filesizewav; q++)
{
writer.Write(s1[q]);
}
writer.Flush();
writer.Close(); // close wav file
stream.Close(); // close stream
console.callsignTextBox.BackColor = Color.MediumSpringGreen; // green if you created it or its still a valid wave
console.menuStrip1.Invalidate();
console.menuStrip1.Update();
createBoxTS.Checked = false; // do only 1 time
} // CreateWaterfallID (this is run as a Thread)
//=============================================================================================
// ke9ns
public static byte QAF = 0;
public void chkQuickAudioFolder_CheckedChanged(object sender, EventArgs e)
{
if (chkQuickAudioFolder.Checked)
{
System.IO.Directory.CreateDirectory(console.AppDataPath + "QuickAudio"); // ke9ns create sub directory
}
else
{
}
} // chkQuickAudioFolder_CheckedChanged
// ke9ns add
private void chkBoxMP3_CheckedChanged(object sender, EventArgs e)
{
}
//===========================================================================
// ke9ns add
private void checkBoxVoice_CheckedChanged(object sender, EventArgs e)
{
chkQuickAudioFolder.Checked = true;
console.checkBoxID.Checked = true;
if (checkBoxVoice.Checked == true)
{
oldmode = console.RX1DSPMode;
if ((oldmode == DSPMode.FM) || (oldmode == DSPMode.AM) || (oldmode == DSPMode.SAM) || (oldmode == DSPMode.DSB)) console.RX1DSPMode = DSPMode.USB; // record only in SSB mode
}
if (console.ckQuickRec.Checked == true) // recorder already running
{
console.ckQuickRec.Checked = false;
string file_name1 = console.AppDataPath + "QuickAudio" + "\\IDTIMER.wav";
string[] files = Directory.GetFiles(console.AppDataPath + "QuickAudio" + "\\", "SDRQuickAudio" + QAC.ToString() +"*.wav"); // ke9ns find file but ignore extra information about file
MessageBox.Show(new Form() { TopMost = true }, "Done Recording.\nIDTIMER.wav file will be created.");
console.RX1DSPMode = oldmode;
if (!File.Exists((file_name1))) // ke9ns check if file name works
{
System.IO.File.Delete(file_name1); // delete the IDTIMER file first
}
System.IO.File.Copy(files[0], file_name1, true); // copy quickaudio file to IDTIMER file
}
else
{
console.ckQuickRec.Checked = true; // start recording
}
} // checkBoxVoice_CheckedChanged
//==================================================================================================================
// ke9ns add
private void checkBoxCW_CheckedChanged(object sender, EventArgs e)
{
chkQuickAudioFolder.Checked = true;
console.checkBoxID.Checked = true;
if (checkBoxCW.Checked == true)
{
oldmode = console.RX1DSPMode;
if ((oldmode == DSPMode.FM) || (oldmode == DSPMode.AM) || (oldmode == DSPMode.SAM) || (oldmode == DSPMode.DSB)) console.RX1DSPMode = DSPMode.USB; // record only in SSB mode
}
if (console.ckQuickRec.Checked == true) // recorder already running
{
console.ckQuickRec.Checked = false;
string file_name1 = console.AppDataPath + "QuickAudio" + "\\IDTIMERCW.wav";
string[] files = Directory.GetFiles(console.AppDataPath + "QuickAudio" + "\\", "SDRQuickAudio" + QAC.ToString() + "*.wav"); //
MessageBox.Show(new Form() { TopMost = true }, "Done Recording.\nIDTIMERCW.wav file will be created.");
console.RX1DSPMode = oldmode;
if (!File.Exists((file_name1))) // ke9ns check if file name works
{
System.IO.File.Delete(file_name1); // delete the IDTIMERCW file first
}
System.IO.File.Copy(files[0], file_name1, true); // copy quickaudio file to IDTIMERCW file
}
else
{
console.ckQuickRec.Checked = true; // start recording
}
} // checkBoxCW_CheckedChanged
DSPMode oldmode = DSPMode.FIRST;
//==================================================================================================================
// ke9ns add IDVOICE
private void checkBoxCQ_CheckedChanged(object sender, EventArgs e)
{
chkQuickAudioFolder.Checked = true;
console.checkBoxID.Checked = true; // REC/PLAY ID checkbox in console
if (checkBoxCQ.Checked == true)
{
oldmode = console.RX1DSPMode;
if ((oldmode == DSPMode.FM) || (oldmode == DSPMode.AM) || (oldmode == DSPMode.SAM) || (oldmode == DSPMode.DSB)) console.RX1DSPMode = DSPMode.USB; // record only in SSB mode
}
if (console.ckQuickRec.Checked == true) // recorder already running
{
console.ckQuickRec.Checked = false;
string file_name1 = console.AppDataPath + "QuickAudio" + "\\CQCQ.wav";
string[] files = Directory.GetFiles(console.AppDataPath + "QuickAudio" + "\\", "SDRQuickAudio" + QAC.ToString() + "*.wav"); //
MessageBox.Show(new Form() { TopMost = true }, "Done Recording.\nCQCQ.wav file will be created.");
console.RX1DSPMode = oldmode;
if (!File.Exists((file_name1))) // ke9ns check if file name works
{
System.IO.File.Delete(file_name1); // delete the cqcq file first
}
System.IO.File.Copy(files[0], file_name1, true); // copy quickaudio file to cqcq file
}
else
{
console.ckQuickRec.Checked = true; // start recording
}
} //checkBoxCQ_CheckedChanged
//==================================================================================
// ke9ns add: REPLY
private void checkBoxTS2_CheckedChanged(object sender, EventArgs e)
{
chkQuickAudioFolder.Checked = true;
console.checkBoxID.Checked = true;
if (checkBoxTS2.Checked == true)
{
oldmode = console.RX1DSPMode;
if ((oldmode == DSPMode.FM) || (oldmode == DSPMode.AM) || (oldmode == DSPMode.SAM) || (oldmode == DSPMode.DSB))
{
console.RX1DSPMode = DSPMode.USB; // record only in SSB mode
}
}
if (console.ckQuickRec.Checked == true) // recorder already running
{
console.ckQuickRec.Checked = false;
string file_name1 = console.AppDataPath + "QuickAudio" + "\\CALL.wav";
string[] files = Directory.GetFiles(console.AppDataPath + "QuickAudio" + "\\", "SDRQuickAudio" + QAC.ToString() + "*.wav"); //
MessageBox.Show(new Form() { TopMost = true }, "Done Recording.\nCALL.wav file will be created.");
console.RX1DSPMode = oldmode;
if (!File.Exists((file_name1))) // ke9ns check if file name works
{
System.IO.File.Delete(file_name1); // delete the call file first
}
System.IO.File.Copy(files[0], file_name1, true); // copy quickaudio file to call file
}
else
{
console.ckQuickRec.Checked = true; // start recording
}
} // checkBoxTS2_CheckedChanged
//=================================================================================
// ke9ns add open MP3 folder
private void checkBoxTS1_CheckedChanged(object sender, EventArgs e)
{
if ((chkQuickAudioFolder.Checked == true) && (chkBoxMP3.Checked == true))
{
string filePath = console.AppDataPath + "QuickAudioMP3";
Debug.WriteLine("mp3 path: " + filePath);
if (!Directory.Exists(filePath))
{
Debug.WriteLine("no mp3 folder found");
return;
}
string argument = @filePath; //@"/select, " + filePath;
System.Diagnostics.Process.Start("explorer.exe", argument);
} //
} // checkBoxTS1_CheckedChanged
private void chkAlwaysOnTop_CheckedChanged(object sender, EventArgs e)
{
this.TopMost = chkAlwaysOnTop.Checked;
}
//================================================================================================================
//================================================================================================================
//================================================================================================================
//================================================================================================================
//
//k6jca End Quick Record & Play
//
////////////////////////
//===================================================================
// ke9ns add
public string QAName()
{
string temp = "__" + console.RX1DSPMode.ToString() + "_"; // DSP mode
temp += console.VFOAFreq.ToString("f6") + "MHz_"; // Freq
temp += DateTime.Now.ToString(); // Date and time
temp = temp.Replace("/", "-");
temp = temp.Replace(":", "_");
return temp;
} // QAName()
} // Class wavecontrol
#region Wave File Header Helper Classes
public class Chunk
{
public int chunk_id;
public static Chunk ReadChunk(ref BinaryReader reader)
{
int data = reader.ReadInt32();
if(data == 0x46464952) // RIFF chunk
{
RIFFChunk riff = new RIFFChunk();
riff.chunk_id = data;
riff.file_size = reader.ReadInt32();
riff.riff_type = reader.ReadInt32();
return riff;
}
else if(data == 0x20746D66) // fmt chunk
{
fmtChunk fmt = new fmtChunk();
fmt.chunk_id = data;
fmt.chunk_size = reader.ReadInt32();
fmt.format = reader.ReadInt16();
fmt.channels = reader.ReadInt16();
fmt.sample_rate = reader.ReadInt32();
fmt.bytes_per_sec = reader.ReadInt32();
fmt.block_align = reader.ReadInt16();
fmt.bits_per_sample = reader.ReadInt16();
return fmt;
}
else if(data == 0x61746164) // data chunk
{
dataChunk data_chunk = new dataChunk();
data_chunk.chunk_id = data;
data_chunk.chunk_size = reader.ReadInt32();
return data_chunk;
}
else
{
Chunk c = new Chunk();
c.chunk_id = data;
return c;
}
}
}
public class RIFFChunk : Chunk
{
public int file_size;
public int riff_type;
}
public class fmtChunk : Chunk
{
public int chunk_size;
public short format;
public short channels;
public int sample_rate;
public int bytes_per_sec;
public short block_align;
public short bits_per_sample;
}
public class dataChunk : Chunk
{
public int chunk_size;
public int[] data;
}
#endregion
#region WaveFile Class
public class WaveFile
{
#region Variable Declaration
private string filename;
private int format;
private int sample_rate;
private int channels;
private TimeSpan length;
private bool valid = false;
#endregion
#region Constructor
public WaveFile(string file)
{
RIFFChunk riff = null;
fmtChunk fmt = null;
dataChunk data_chunk = null;
filename = file;
if(!File.Exists(filename))
{
valid = false;
return;
}
BinaryReader reader = null;
try
{
reader = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read));
}
catch(Exception)
{
MessageBox.Show("File is already open.");
valid = false;
return;
}
while((data_chunk == null ||
riff == null || fmt == null) &&
reader.PeekChar() != -1)
{
Chunk chunk = Chunk.ReadChunk(ref reader);
if(chunk.GetType() == typeof(RIFFChunk))
riff = (RIFFChunk)chunk;
else if(chunk.GetType() == typeof(fmtChunk))
fmt = (fmtChunk)chunk;
else if(chunk.GetType() == typeof(dataChunk))
data_chunk = (dataChunk)chunk;
}
reader.Close();
format = fmt.format;
sample_rate = fmt.sample_rate;
channels = fmt.channels;
if(fmt.bytes_per_sec == 0)
{
valid = false;
return;
}
length = new TimeSpan(0, 0, data_chunk.data.Length / fmt.bytes_per_sec);
valid = true;
}
#endregion
#region Properties
public int Format
{
get { return format; }
}
public int SampleRate
{
get { return sample_rate; }
}
public int Channels
{
get { return channels; }
}
public TimeSpan Length
{
get { return length; }
}
public bool Valid
{
get { return valid; }
}
#endregion
#region Misc Routines
public new string ToString()
{
string s = filename.PadRight(20, ' ');
s += length.Hours.ToString("10") + ":" +
length.Minutes.ToString("nn") + ":" +
length.Seconds.ToString("nn");
return s;
}
#endregion
}
#endregion
#region Playlist
public class Playlist
{
//ArrayList wave_files;
public void Add(WaveFile w)
{
//wave_files.Add(w);
}
public void Remove(int i)
{
//wave_files.RemoveAt(i);
}
}
#endregion
#region Wave File Writer Class
//=====================================================================================================
//=====================================================================================================
// ke9ns create a wave file from receive audio on the flex
//=====================================================================================================
//=====================================================================================================
unsafe public class WaveFileWriter
{
private BinaryWriter writer;
private bool record;
private int frames_per_buffer;
private short channels;
private int sample_rate;
private int length_counter;
private RingBufferFloat rb_l;
private RingBufferFloat rb_r;
private float[] in_buf_l;
private float[] in_buf_r;
private float[] out_buf_l;
private float[] out_buf_r;
private float[] out_buf;
private byte[] byte_buf;
private const int IN_BLOCK = 2048;
private string filename;
unsafe private void* resamp_l, resamp_r;
public WaveFileWriter(int frames, short chan, int samp_rate, string file)
{
frames_per_buffer = frames;
channels = chan;
sample_rate = samp_rate;
int OUT_BLOCK = (int)Math.Ceiling(IN_BLOCK*(double)sample_rate/Audio.SampleRate1);
rb_l = new RingBufferFloat(IN_BLOCK*16);
rb_r = new RingBufferFloat(IN_BLOCK*16);
in_buf_l = new float[IN_BLOCK];
in_buf_r = new float[IN_BLOCK];
out_buf_l = new float[OUT_BLOCK];
out_buf_r = new float[OUT_BLOCK];
out_buf = new float[OUT_BLOCK*2];
byte_buf = new byte[OUT_BLOCK*2*4];
length_counter = 0;
record = true;
if(sample_rate != Audio.SampleRate1)
{
resamp_l = DttSP.NewResamplerF(Audio.SampleRate1, sample_rate);
if(channels > 1) resamp_r = DttSP.NewResamplerF(Audio.SampleRate1, sample_rate);
}
try
{
writer = new BinaryWriter(File.Open(file, FileMode.Create));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
filename = file;
Thread t = new Thread(new ThreadStart(ProcessRecordBuffers));
t.Name = "Wave File Write Thread";
t.IsBackground = true;
t.Priority = ThreadPriority.Normal;
t.Start();
} // wavefilewriter
private void ProcessRecordBuffers()
{
WriteWaveHeader(ref writer, channels, sample_rate, 32, 0);
while(record == true || rb_l.ReadSpace() > 0)
{
while(rb_l.ReadSpace() > IN_BLOCK ||
(record == false && rb_l.ReadSpace() > 0))
{
WriteBuffer(ref writer, ref length_counter);
}
Thread.Sleep(3);
}
writer.Seek(0, SeekOrigin.Begin);
WriteWaveHeader(ref writer, channels, sample_rate, 32, length_counter);
writer.Flush();
writer.Close();
}
unsafe public void AddWriteBuffer(float *left, float *right)
{
rb_l.WritePtr(left, frames_per_buffer);
rb_r.WritePtr(right, frames_per_buffer);
//Debug.WriteLine("ReadSpace: "+rb.ReadSpace());
}
public string Stop()
{
record = false;
return filename;
}
private void WriteBuffer(ref BinaryWriter writer, ref int count)
{
int cnt = rb_l.Read(in_buf_l, IN_BLOCK);
rb_r.Read(in_buf_r, IN_BLOCK);
int out_cnt = IN_BLOCK;
// resample
if(sample_rate != Audio.SampleRate1)
{
fixed(float* in_ptr = &in_buf_l[0])
fixed(float* out_ptr = &out_buf_l[0])
DttSP.DoResamplerF(in_ptr, out_ptr, cnt, &out_cnt, resamp_l);
if(channels > 1)
{
fixed(float* in_ptr = &in_buf_r[0])
fixed(float* out_ptr = &out_buf_r[0])
DttSP.DoResamplerF(in_ptr, out_ptr, cnt, &out_cnt, resamp_r);
}
}
else
{
in_buf_l.CopyTo(out_buf_l, 0);
in_buf_r.CopyTo(out_buf_r, 0);
}
if(channels > 1)
{
// interleave samples
for(int i=0; i<out_cnt; i++)
{
out_buf[i*2] = out_buf_l[i];
out_buf[i*2+1] = out_buf_r[i];
}
}
else
{
out_buf_l.CopyTo(out_buf, 0);
}
byte[] temp = new byte[4];
int length = out_cnt;
if(channels > 1) length *= 2;
for(int i=0; i<length; i++)
{
temp = BitConverter.GetBytes(out_buf[i]);
for(int j=0; j<4; j++)
byte_buf[i*4+j] = temp[j];
}
writer.Write(byte_buf, 0, out_cnt*2*4);
count += out_cnt*2*4;
}
// ke9ns: write a wav file (header)
private void WriteWaveHeader(ref BinaryWriter writer, short channels, int sample_rate, short bit_depth, int data_length)
{
writer.Write(0x46464952); // "RIFF" -- descriptor chunk ID
writer.Write(data_length + 36); // size of whole file -- 1 for now
writer.Write(0x45564157); // "WAVE" -- descriptor type
writer.Write(0x20746d66); // "fmt " -- format chunk ID
writer.Write((int)16); // size of fmt chunk
writer.Write((short)3); // FormatTag -- 3 for floats
writer.Write(channels); // wChannels
writer.Write(sample_rate); // dwSamplesPerSec
writer.Write((int)(channels*sample_rate*bit_depth/8)); // dwAvgBytesPerSec
writer.Write((short)(channels*bit_depth/8)); // wBlockAlign
writer.Write(bit_depth); // wBitsPerSample
writer.Write(0x61746164); // "data" -- data chunk ID
writer.Write(data_length); // chunkSize = length of data
writer.Flush(); // write the file
}
}
#endregion
#region Wave File Reader Class
//=============================================================================================
//=============================================================================================
// ke9ns read in wave file data passed from openwavefile()
// start Thread (processbuffers) to play wave file audio while doing other things
//=============================================================================================
//=============================================================================================
unsafe public class WaveFileReader1
{
private WaveControl wave_form;
private BinaryReader reader;
private int format;
private int sample_rate;
private int channels;
private bool playback;
private int frames_per_buffer;
private RingBufferFloat rb_l;
private RingBufferFloat rb_r;
private float[] buf_l_in;
private float[] buf_r_in;
private float[] buf_l_out;
private float[] buf_r_out;
private int IN_BLOCK;
private int OUT_BLOCK;
private byte[] io_buf;
private int io_buf_size;
private bool eof = false;
unsafe private void* resamp_l, resamp_r;
private MemoryStream ms;
//=====================================================================================
public WaveFileReader1(
WaveControl form,
int frames,
int fmt,
int samp_rate,
int chan,
ref BinaryReader binread)
{
wave_form = form;
frames_per_buffer = frames;
format = fmt;
sample_rate = samp_rate;
channels = chan;
//OUT_BLOCK = 2048;
//IN_BLOCK = (int)Math.Floor(OUT_BLOCK*(double)sample_rate/Audio.SampleRate1);
//OUT_BLOCK = (int)Math.Ceiling(IN_BLOCK*Audio.SampleRate1/(double)sample_rate);
IN_BLOCK = 2048;
OUT_BLOCK = (int)Math.Ceiling(IN_BLOCK*Audio.SampleRate1/(double)sample_rate); // SampleRate1 = SR of the Flex, Sample_Rate = the wave file SR
rb_l = new RingBufferFloat(16*OUT_BLOCK);
rb_r = new RingBufferFloat(16*OUT_BLOCK);
buf_l_in = new float[IN_BLOCK]; // floating arrays
buf_r_in = new float[IN_BLOCK];
buf_l_out = new float[OUT_BLOCK];
buf_r_out = new float[OUT_BLOCK];
if(format == 1) // Format = 1 = PCM (2byte SINGLE)
{
io_buf_size = IN_BLOCK*2*2;
if (sample_rate != Audio.SampleRate1) // ke9ns add (this code was only in format==3, but copied it to format==1 If Flex and wave file SR dont match
{
resamp_l = DttSP.NewResamplerF(sample_rate, Audio.SampleRate1); // LEFT
if (channels > 1) resamp_r = DttSP.NewResamplerF(sample_rate, Audio.SampleRate1); // RIGHT
}
}
else if(format == 3) // Format = 3 = ?? (float 4bytes, instead of SINGLE 2 bytes
{
io_buf_size = IN_BLOCK*4*2;
if(sample_rate != Audio.SampleRate1) // If Flex and wave file SR dont match
{
resamp_l = DttSP.NewResamplerF(sample_rate, Audio.SampleRate1); // LEFT
if(channels > 1) resamp_r = DttSP.NewResamplerF(sample_rate, Audio.SampleRate1); // RIGHT
}
} // format = 3
io_buf = new byte[io_buf_size];
playback = true;
reader = binread;
Thread t = new Thread(new ThreadStart(ProcessBuffers)); // thread to play audio "ProcessBuffers" without halting the radio
t.Name = "Wave File Read Thread";
t.IsBackground = true;
t.Priority = ThreadPriority.Normal;
do
{
ReadBuffer(ref reader);
} while(rb_l.WriteSpace() > OUT_BLOCK && !eof); // do ReadBuffer to tak eout the leadin wave whitespace before handing it over to the Processbuffer to call the Readbuffer
t.Start();
} // wavefilereader()
//================================================================
//================================================================
// ke9ns This is a THREAD called from wavefilereader() above
// plays wave audio then
// this calls next() which signal end of wave file playback
//================================================================
//================================================================
private void ProcessBuffers()
{
while (playback == true)
{
while (rb_l.WriteSpace() >= OUT_BLOCK && !eof) // check for end of wave file
{
//Debug.WriteLine("loop 2");
ReadBuffer(ref reader); // ke9ns play audio here ?
if(playback == false) goto end;
}
if(playback == false)
goto end;
Thread.Sleep(10);
}
end: // end of playback of wave file
reader.Close(); // close the wave file now
Thread.Sleep(50);
wave_form.Next(); // tall everyone your done
} // processbuffers
//==========================================================================
//==========================================================================
// ke9ns called from Processbuffers THREAD above
// this
//==========================================================================
//==========================================================================
private void ReadBuffer(ref BinaryReader reader)
{
// Debug.WriteLine("ReadBuffer ("+rb_l.ReadSpace()+")");
int i=0, num_reads = IN_BLOCK;
int val = reader.Read(io_buf, 0, io_buf_size); // reader. this is the open wave file binearystream
if(val < io_buf_size)
{
eof = true;
switch(format)
{
case 1: // ints
num_reads = val / 4;
break;
case 3: // floats
num_reads = val / 8;
break;
}
} // if
for(; i < num_reads; i++)
{
switch(format)
{
case 1: // FORMAT 1 = PCM = ints
buf_l_in[i] = (float)((double)BitConverter.ToInt16(io_buf, i * 4) / 32767.0); // LEFT wave files are 2bytes (16bit) data saved as +/- 0 to 32767
if (channels > 1) buf_r_in[i] = (float)((double)BitConverter.ToInt16(io_buf, i * 4 + 2) / 32767.0); // RIGHT buf_r_in[i] is now ke9ns MOD no channels if
break;
case 3: // FORMAT 3 = ??? floats
buf_l_in[i] = BitConverter.ToSingle(io_buf, i*8); // LEFT wave files are 4 bytes (float) each data point
if (channels > 1) buf_r_in[i] = BitConverter.ToSingle(io_buf, i * 8 + 4); // RIGHT ke9ns MOD no channels if
break;
}
} // for
if(num_reads < IN_BLOCK) // BAD clear out buffer and STOP
{
for (int j = i; j < IN_BLOCK; j++)
{
buf_l_in[j] = buf_r_in[j] = 0.0f;
}
playback = false;
reader.Close(); // wave file is now closed
}
int out_cnt = IN_BLOCK;
if(sample_rate != Audio.SampleRate1)
{
fixed (float* in_ptr = &buf_l_in[0]) // PLAY LEFT
{
fixed (float* out_ptr = &buf_l_out[0])
{
DttSP.DoResamplerF(in_ptr, out_ptr, IN_BLOCK, &out_cnt, resamp_l);
}
}
if (channels > 1) // play RIGHT
{
fixed(float* in_ptr = &buf_r_in[0])
{
fixed (float* out_ptr = &buf_r_out[0])
{
DttSP.DoResamplerF(in_ptr, out_ptr, IN_BLOCK, &out_cnt, resamp_r);
}
}
}
}
else
{
buf_l_in.CopyTo(buf_l_out, 0); // copy to buffer
if (channels > 1)
{
buf_r_in.CopyTo(buf_r_out, 0); // ke9ns mod (no if channels)
// Debug.WriteLine("channels2==================");
}
}
//-----------------------------------------------------------
rb_l.Write(buf_l_out, out_cnt); // play left channel
if (channels > 1)
{
rb_r.Write(buf_r_out, out_cnt); // play right channel
}
else
{
rb_r.Write(buf_l_out, out_cnt); // if only left channel, simply repeat right
}
// Debug.WriteLine("readbuffer==================");
} // readbuffer
//=====================================================================================================
// ke9ns play wav files back
unsafe public void GetPlayBuffer(float *left, float *right)
{
// Debug.WriteLine("GetPlayBuffer ("+rb_l.ReadSpace()+")");
int count = rb_l.ReadSpace();
if(count == 0) return;
if(count > frames_per_buffer) count = frames_per_buffer;
rb_l.ReadPtr(left, count); // LEFT
rb_r.ReadPtr(right, count); // RIGHT
if(count < frames_per_buffer) // BAD
{
for (int i = count; i < frames_per_buffer; i++)
{
left[i] = right[i] = 0.0f;
}
}
}
// FIXME: implement interleaved version of Get Play Buffer
//======================================================================
public void Stop()
{
playback = false;
}
} // class wavefilereader
#endregion
}