AudioEditorForm.cs
Download AudioEditorForm.cs File
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using NAudio;
using NAudio.Wave;
using System.Speech;
using System.Speech.Recognition;
using Microsoft.VisualBasic;
namespace VoiceEditor_Capstone
{
public partial class VoiceEditorForm : Form
{
public VoiceEditorForm()
{
InitializeComponent();
}
//DATA BITS//
static string directoryPath = AppDomain.CurrentDomain.BaseDirectory.ToString();
static string voiceDirectory = directoryPath + @ " Voices\ " ;
static string workingDirectory = directoryPath + @ " WorkingData\ " ;
string selectedVoiceDirectory = null;
string selectedRecordDirectory = null;
List < string > voices = null;
string selectedVoice = null;
private WaveFileReader waveReader = null;
private DirectSoundOut waveOut = null;
private WaveIn wi = null;
private WaveOut wo = null;
private WaveFileWriter waveWriter = null;
bool recording = false;
string recordedFilePath = null;
string sourceWavefile = null;
string workingWavefile = null;
string constructWavefile = null;
string latestRecording = null;
string trimmedWav = null;
string oldTrimmedWav = null;
string construct = null;
private void VoiceEditorForm_Load(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Maximized;
//ensure working directory exists
directoryExist(workingDirectory);
//populate voice directory
voices = new List < string > ();
directoryExist(voiceDirectory);
foreach(var directory in Directory.GetDirectories(voiceDirectory))
voices.Add(directory);
voicesComboBox.Items.Add( " < Add New Voice > " );
foreach (var voice in voices)
voicesComboBox.Items.Add(Path.GetFileName(voice));
}
//OPEN WAV FILES//
private void openSourceWav(string file)
{
sourceWavefile = file;
sourceWaveViewer.WaveStream = new WaveFileReader(file);
sourceWaveViewer.FitToScreen();
}
private void openWorkingWav(string file)
{
workingWavefile = file;
workingWaveViewer.WaveStream = new WaveFileReader(file);
workingWaveViewer.FitToScreen();
}
private void openConstructWav(string file)
{
constructWavefile = file;
constructWaveViewer.WaveStream = new WaveFileReader(file);
constructWaveViewer.FitToScreen();
}
//SHOW WAVEFORM//
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.Filter = " Wave File (*.wav)|*.wav; " ;
if (open.ShowDialog() != DialogResult.OK)
return;
openSourceWav(open.FileName);
}
//PLAYING WAV FILES//
private void playWav(string waveFile)
{
disposeWave();
waveReader = new WaveFileReader(waveFile);
waveOut = new DirectSoundOut();
waveOut.Init(new WaveChannel32(waveReader));
if (waveOut != null)
{
waveOut.Play();
}
}
private void playToolStripMenuItem1_Click(object sender, EventArgs e)
{
playWav(sourceWavefile);
//disposeWave();
//waveReader = new WaveFileReader(sourceWavefile);
//waveOut = new DirectSoundOut();
//waveOut.Init(new WaveChannel32(waveReader));
//if (waveOut != null)
//{
// waveOut.Play();
//}
}
//RECORDING WAV FILES//
private void wi_DataAvailable(object sender, WaveInEventArgs e)
{
waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
int seconds = (int)(waveWriter.Length / waveWriter.WaveFormat.AverageBytesPerSecond);
if (seconds > 120)
wi.StopRecording();
}
private void wi_RecordingStopped(object sender, EventArgs e)
{
wi.Dispose();
waveWriter.Close();
waveWriter.Dispose();
waveWriter = null;
updateOpenSourceWav(latestRecording);
}
private void updateOpenSourceWav(string wavFilePath)
{
if (File.Exists(wavFilePath))
openSourceWav(wavFilePath);
}
//TRIM WAVE FILES//
public void TrimWave(string waveIn, string waveOut, TimeSpan fromStart, TimeSpan fromEnd)
{
disposeWave();
using(WaveFileReader wfr = new WaveFileReader(waveIn))
{
using (WaveFileWriter wfw = new WaveFileWriter(waveOut, wfr.WaveFormat))
{
int bytesPerMillisecond = wfr.WaveFormat.AverageBytesPerSecond / 1000;
int start = (int)fromStart.TotalMilliseconds * bytesPerMillisecond;
start = start - start % wfr.WaveFormat.BlockAlign; //move start back to nearest block
int endBytes = (int)fromEnd.TotalMilliseconds * bytesPerMillisecond;
endBytes = endBytes - endBytes % wfr.WaveFormat.BlockAlign;
int end = (int)wfr.Length - endBytes;
TrimWaveFile(wfr, wfw, start, end);
//wfr.Dispose();
//wfw.Dispose();
}
}
}
private void TrimWaveFile(WaveFileReader wfr, WaveFileWriter wfw, int startPos, int endPos)
{
{
wfr.Position = startPos;
byte[] buffer = new byte[1024];
while (wfr.Position < endPos)
{
int bytesRequired = (int)(endPos - wfr.Position);
if (bytesRequired > 0)
{
int bytesToRead = Math.Min(bytesRequired, buffer.Length);
int bytesRead = wfr.Read(buffer, 0, bytesToRead);
if (bytesRead > 0)
{
wfw.Write(buffer, 0, bytesRead);
}
}
}
}
}
//JOINING WAVE FILES//
public static void Concatenate(string outputFile, IEnumerable < string > sourceFiles)
{
byte[] buffer = new byte[1024];
WaveFileWriter wfw = null;
try
{
foreach(string file in sourceFiles)
{
using(WaveFileReader reader = new WaveFileReader(file))
{
if (wfw == null)
wfw = new WaveFileWriter(outputFile, reader.WaveFormat);
else
{
if (!reader.WaveFormat.Equals(wfw.WaveFormat))
throw new InvalidOperationException( " Can't concatenate. Filetype mismatch. " );
}
int read;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
wfw.Write(buffer, 0, read);
}
}
}
finally
{
if (wfw != null)
wfw.Dispose();
}
}
//ADDING NEW VOICE DIRECTORIES//
private void addVoiceDirectory(string directoryPath)
{
Directory.CreateDirectory(directoryPath);
}
//OTHER TOOLS//
private void directoryExist(string directory) //Determines if a given directory exists. If not, creates it.
{
if(!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
//PLAYING TIMER / POSITION TRACKER//
public Timer playTimer;
double wavPosition;
double lastWavPosition;
public void sourcePlayLine()
{
if(playTimer != null)
disposePlayTimer();
wavPosition = (double)(sourceWaveViewer.pixelPerMillisecond() * waveReader.CurrentTime.TotalMilliseconds);
lastWavPosition = wavPosition;
sourceWaveViewer.drawWavePosition(wavPosition);
playTimer = new Timer();
playTimer.Interval = 1;
playTimer.Tick += new EventHandler(sourcePlayTimer_Tick);
playTimer.Enabled = true;
playTimer.Start();
}
private void sourcePlayTimer_Tick(object sender, EventArgs e)
{
wavPosition = (double)(sourceWaveViewer.pixelPerMillisecond() * waveReader.CurrentTime.TotalMilliseconds);
sourceWaveViewer.drawWavePosition(lastWavPosition);
sourceWaveViewer.drawWavePosition(wavPosition);
lastWavPosition = wavPosition;
if (wavPosition > = sourceWaveViewer.Width)
{
playTimer.Enabled = false;
sourceWaveViewer.drawWavePosition(lastWavPosition);
disposePlayTimer();
}
}
public void workingPlayLine()
{
if (playTimer != null)
disposePlayTimer();
wavPosition = (double)(workingWaveViewer.pixelPerMillisecond() * waveReader.CurrentTime.TotalMilliseconds);
lastWavPosition = wavPosition;
workingWaveViewer.drawWavePosition(wavPosition);
playTimer = new Timer();
playTimer.Interval = 1;
playTimer.Tick += new EventHandler(workingPlayTimer_Tick);
playTimer.Enabled = true;
playTimer.Start();
}
private void workingPlayTimer_Tick(object sender, EventArgs e)
{
wavPosition = (double)(workingWaveViewer.pixelPerMillisecond() * waveReader.CurrentTime.TotalMilliseconds);
workingWaveViewer.drawWavePosition(lastWavPosition);
workingWaveViewer.drawWavePosition(wavPosition);
lastWavPosition = wavPosition;
if (wavPosition > = workingWaveViewer.Width)
{
playTimer.Enabled = false;
workingWaveViewer.drawWavePosition(lastWavPosition);
disposePlayTimer();
}
}
public void constructPlayLine()
{
if (playTimer != null)
disposePlayTimer();
wavPosition = (double)(constructWaveViewer.pixelPerMillisecond() * waveReader.CurrentTime.TotalMilliseconds);
lastWavPosition = wavPosition;
constructWaveViewer.drawWavePosition(wavPosition);
playTimer = new Timer();
playTimer.Interval = 1;
playTimer.Tick += new EventHandler(constructPlayTimer_Tick);
playTimer.Enabled = true;
playTimer.Start();
}
private void constructPlayTimer_Tick(object sender, EventArgs e)
{
wavPosition = (double)(constructWaveViewer.pixelPerMillisecond() * waveReader.CurrentTime.TotalMilliseconds);
constructWaveViewer.drawWavePosition(lastWavPosition);
constructWaveViewer.drawWavePosition(wavPosition);
lastWavPosition = wavPosition;
if (wavPosition > = constructWaveViewer.Width)
{
playTimer.Enabled = false;
constructWaveViewer.drawWavePosition(lastWavPosition);
disposePlayTimer();
}
}
private void disposePlayTimer()
{
if(playTimer != null)
{
playTimer.Stop();
playTimer.Enabled = false;
playTimer.Dispose();
playTimer = null;
}
sourceWaveViewer.FitToScreen();
workingWaveViewer.FitToScreen();
constructWaveViewer.FitToScreen();
}
//CLEANUP//
private void disposeWave()
{
if(waveOut != null)
{
if (waveOut.PlaybackState == NAudio.Wave.PlaybackState.Playing)
waveOut.Stop();
waveOut.Dispose();
waveOut = null;
}
if(waveReader != null)
{
waveReader.Dispose();
waveReader = null;
}
}
private void VoiceEditorForm_FormClosing(object sender, FormClosingEventArgs e)
{
disposeWave();
}
//BUTTON CLICK EVENTS//
private void sourcePlayBtn_Click(object sender, EventArgs e)
{
if (sourceWavefile != null)
{
playWav(sourceWavefile);
sourcePlayLine();
}
}
private void workingPlayBtn_Click(object sender, EventArgs e)
{
if (workingWavefile != null)
{
playWav(workingWavefile);
workingPlayLine();
}
}
private void sourceRecordBtn_Click(object sender, EventArgs e)
{
if (!recording)
{
if (sourceWavefile != null)
{
var userConfirm = MessageBox.Show( " An audio wave source already exists. If you continue, any unsaved data will be lost. " , " Continue? " , MessageBoxButtons.YesNo);
if (userConfirm == DialogResult.No)
return;
}
recording = true;
sourceRecordBtn.Text = " Stop Recording " ;
wi = new WaveIn(WaveCallbackInfo.FunctionCallback());
latestRecording = selectedRecordDirectory + " recordedWav( " + DateTime.Now.ToString( " yyyy-MM-dd_hh-mm-ss " ) + " ).wav " ;
waveWriter = new WaveFileWriter(latestRecording, wi.WaveFormat);
wi.DataAvailable += new EventHandler < WaveInEventArgs > (wi_DataAvailable);
wi.RecordingStopped += new EventHandler < StoppedEventArgs > (wi_RecordingStopped);
wi.WaveFormat = new WaveFormat(8000, 1);
wi.StartRecording();
}
else //recording
{
recording = false;
sourceRecordBtn.Text = " Record " ;
wi.StopRecording();
//wi.Dispose();
//waveWriter.Dispose();
//openSourceWav(latestRecording);
}
}
private void sourceTrimBtn_Click(object sender, EventArgs e)
{
disposePlayTimer();
trimmedWav = selectedRecordDirectory + @ " trimmedSource " + DateTime.Now.ToString( " yyyy-MM-dd_hh-mm-ss " ) + " ).wav " ;
TrimWave(sourceWavefile, trimmedWav, sourceWaveViewer.fromStart, sourceWaveViewer.fromEnd);
//playWav(trimmedWav);
openWorkingWav(trimmedWav);
}
private void workingSaveBtn_Click(object sender, EventArgs e)
{
if (wordTxtbox.Text == null)
{
MessageBox.Show( " Please enter what word is being saved in the textbox to the right. " );
return;
}
if (File.Exists(selectedVoiceDirectory + " \\ " + wordTxtbox.Text + " .wav " ))
{
var userConfirm = MessageBox.Show( " An audio clip for this word already exists for the selected user. Overwrite with the new clip? " , " Overwrite? " , MessageBoxButtons.YesNo);
if (userConfirm == DialogResult.No)
return;
else
File.Delete(selectedVoiceDirectory + " \\ " + wordTxtbox.Text + " .wav " );
}
File.Copy(trimmedWav, selectedVoiceDirectory + " \\ " + wordTxtbox.Text + " .wav " );
}
private void constructPlayBtn_Click(object sender, EventArgs e)
{
if (constructWavefile != null)
{
playWav(constructWavefile);
constructPlayLine();
}
}
//WIP FUNCTIONS//
private void voicesComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (voicesComboBox.Text == " < Add New Voice > " )
{
string input = Interaction.InputBox( " Enter voice name. " , " Add New Voice " , " " , -1, -1);
Regex rgx = new Regex(@ " [^\w\s] " );
string cleanedInput = rgx.Replace(input, string.Empty);
if (cleanedInput != " " )
{
bool voiceExists = false;
foreach (string name in voicesComboBox.Items)
{
if (name == cleanedInput)
{
MessageBox.Show( " Voice files already exist under this name. " );
voiceExists = true;
}
}
if (!voiceExists)
{
voicesComboBox.Items.Add(cleanedInput);
directoryExist(voiceDirectory + cleanedInput);
voicesComboBox.Text = cleanedInput;
selectedVoice = cleanedInput;
}
}
else
{
if(input != " " )
MessageBox.Show(input);
}
}
else
{
selectedVoice = voicesComboBox.Text;
selectedVoiceDirectory = voiceDirectory + selectedVoice + @ " \VoiceData " ;
selectedRecordDirectory = voiceDirectory + selectedVoice + @ " \RawData " ;
directoryExist(selectedVoiceDirectory);
directoryExist(selectedRecordDirectory);
}
}
private void constructButton_Click(object sender, EventArgs e)
{
if(selectedVoice != null)
{
string concatenation = null;
string desiredPhrase = phraseBox.Text;
Regex rgx = new Regex( " [^a-zA-Z -] " );
string parsedPhrase = rgx.Replace(desiredPhrase, " " );
parsedPhrase = parsedPhrase.ToLower();
string[] phrase = parsedPhrase.Split(' ');
List < string > files = new List < string > ();
foreach (string word in phrase)
{
string findFile = selectedVoiceDirectory + " \\ " + word + " .wav " ;
//string findFile = @ " C:\Users\Anumidium\Desktop\Capstone Project\VoiceEditor_Capstone\VoiceEditor_Capstone\bin\Debug\VoiceData\bradblank\hello.wav " ;
if (File.Exists(findFile))
files.Add(findFile);
else
MessageBox.Show( " No match for ' " + word + " ' in " + voicesComboBox.Text + " 's directory. " );
}
concatenation = desiredPhrase + " ( " + DateTime.Now.ToString( " yyyy-MM-dd_hh-mm-ss " ) + " ) " ;
Concatenate(workingDirectory + concatenation + " .wav " , files);
openConstructWav(workingDirectory + concatenation + " .wav " );
}
}
private void playSelectedToolStripMenuItem_Click(object sender, EventArgs e)
{
string trimmedWav = workingDirectory + @ " trimmedSource.wav " ;
TrimWave(sourceWavefile, trimmedWav, sourceWaveViewer.fromStart, sourceWaveViewer.fromEnd);
playWav(trimmedWav);
openWorkingWav(trimmedWav);
}
private void reTrimButton_Click(object sender, EventArgs e)
{
disposePlayTimer();
oldTrimmedWav = trimmedWav;
trimmedWav = selectedRecordDirectory + @ " trimmedSource " + DateTime.Now.ToString( " yyyy-MM-dd_hh-mm-ss " ) + " ).wav " ;
TrimWave(oldTrimmedWav, trimmedWav, workingWaveViewer.fromStart, workingWaveViewer.fromEnd);
openWorkingWav(trimmedWav);
workingUndoButton.Enabled = true;
}
private void workingUndo_Click(object sender, EventArgs e)
{
workingUndoButton.Enabled = false;
if(oldTrimmedWav != null)
{
trimmedWav = oldTrimmedWav;
oldTrimmedWav = null;
openWorkingWav(trimmedWav);
}
}
private void stopButton_Click(object sender, EventArgs e)
{
disposePlayTimer();
disposeWave();
}
}
}