mirror of
https://github.com/opentx/opentx.git
synced 2025-07-13 11:29:51 +03:00
Added audio processing of recorded files.
This commit is contained in:
parent
bc9650fc0c
commit
cf22b2328b
6 changed files with 198 additions and 17 deletions
|
@ -57,9 +57,7 @@
|
||||||
SelectionChanged="switchLanguage"
|
SelectionChanged="switchLanguage"
|
||||||
Width="200" Height="23" />
|
Width="200" Height="23" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Separator Height="5" />
|
<Separator Height="5" />
|
||||||
<TextBlock Text="Sentence" Margin="5,0,0,0" FontSize="18" />
|
<TextBlock Text="Sentence" Margin="5,0,0,0" FontSize="18" />
|
||||||
<Grid Margin="10,0,0,0" DataContext="{Binding ElementName=lvSentences, Path=SelectedItem}" Width="Auto">
|
<Grid Margin="10,0,0,0" DataContext="{Binding ElementName=lvSentences, Path=SelectedItem}" Width="Auto">
|
||||||
|
@ -82,9 +80,24 @@
|
||||||
<TextBlock Text="Sentence" Grid.Row="2" Grid.Column="0" Margin="0,5,0,0" />
|
<TextBlock Text="Sentence" Grid.Row="2" Grid.Column="0" Margin="0,5,0,0" />
|
||||||
<TextBox Text="{Binding Path=voiceString}" Grid.Row="2" Grid.Column="1" Margin="0,0,10,0"/>
|
<TextBox Text="{Binding Path=voiceString}" Grid.Row="2" Grid.Column="1" Margin="0,0,10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Separator Height="5" Margin="0,5,0,0" />
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
|
||||||
|
<TextBlock Text="Cut Level" Width="70" Margin="10,10,0,0" />
|
||||||
|
<Slider Name="noiceLevelSlider"
|
||||||
|
Value="800"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="4000"
|
||||||
|
TickPlacement="BottomRight"
|
||||||
|
TickFrequency="100"
|
||||||
|
IsSnapToTickEnabled="True"
|
||||||
|
Width="170"
|
||||||
|
Margin="10,10,10,0" ToolTip="Set Cut Level as low as possible" />
|
||||||
|
<TextBlock Text="{Binding ElementName=noiceLevelSlider, Path=Value}" Width="40" Margin="0,10,0,0"/>
|
||||||
|
<TextBlock Text="Voice Rate" Width="70" Margin="10,10,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,5,0,0">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,5,0,0">
|
||||||
<Button Content="New Sentence" Width="120" Height="32" Name="buttonAddItem" Click="addSentence"/>
|
<Button Content="New Sentence" Width="120" Height="32" Name="buttonAddItem" Click="addSentence"/>
|
||||||
<Button Name="btnRecord" ToolTip="Start recording" Click="record" Margin="20,0,0,0" >
|
<Button Name="btnRecord" ToolTip="Start recording" Click="record" Margin="20,0,0,0" >
|
||||||
<Image Height="32" Source="/OpenTXrecorder;component/record.png"/>
|
<Image Height="32" Source="/OpenTXrecorder;component/record.png"/>
|
||||||
|
|
|
@ -161,7 +161,7 @@ namespace OpenTXrecorder
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SoundPlayer player = new SoundPlayer(sentence.fullPath());
|
SoundPlayer player = new SoundPlayer(sentence.fullPath);
|
||||||
player.Play();
|
player.Play();
|
||||||
}
|
}
|
||||||
catch (Exception) { }; // Catch and disregard all media exceptions
|
catch (Exception) { }; // Catch and disregard all media exceptions
|
||||||
|
@ -180,7 +180,7 @@ namespace OpenTXrecorder
|
||||||
isRecording = true;
|
isRecording = true;
|
||||||
lblRecording.Visibility = System.Windows.Visibility.Visible;
|
lblRecording.Visibility = System.Windows.Visibility.Visible;
|
||||||
Sentence sentence = (Sentence)this.lvSentences.SelectedItem;
|
Sentence sentence = (Sentence)this.lvSentences.SelectedItem;
|
||||||
string path = sentence.fullPath();
|
string path = sentence.fullPath;
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(path)); // Create directory if it doesn't exist
|
Directory.CreateDirectory(Path.GetDirectoryName(path)); // Create directory if it doesn't exist
|
||||||
System.IO.File.WriteAllText(path, ""); // Create and flush the file
|
System.IO.File.WriteAllText(path, ""); // Create and flush the file
|
||||||
|
|
||||||
|
@ -199,11 +199,16 @@ namespace OpenTXrecorder
|
||||||
recorder.Close();
|
recorder.Close();
|
||||||
filewriter.Close();
|
filewriter.Close();
|
||||||
|
|
||||||
|
|
||||||
int index = this.lvSentences.SelectedIndex;
|
int index = this.lvSentences.SelectedIndex;
|
||||||
lblRecording.Visibility = System.Windows.Visibility.Hidden;
|
lblRecording.Visibility = System.Windows.Visibility.Hidden;
|
||||||
Sentence sentence = (Sentence)this.lvSentences.SelectedItem;
|
Sentence sentence = (Sentence)this.lvSentences.SelectedItem;
|
||||||
loadLanguage(); // Called to refresh the sentence data of the current langugae
|
loadLanguage(); // Called to refresh the sentence data of the current langugae
|
||||||
this.lvSentences.SelectedIndex = index;
|
this.lvSentences.SelectedIndex = index;
|
||||||
|
|
||||||
|
wavProcessor processor = new wavProcessor();
|
||||||
|
int noiceLevel = (int)this.noiceLevelSlider.Value;
|
||||||
|
processor.StripSilence(sentence.fullPath, noiceLevel );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DataArrived(IntPtr data, int size)
|
private void DataArrived(IntPtr data, int size)
|
||||||
|
@ -235,10 +240,9 @@ namespace OpenTXrecorder
|
||||||
shortLanguage = str;
|
shortLanguage = str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Data container classes
|
||||||
|
|
||||||
/*
|
|
||||||
* Data container classes
|
|
||||||
*/
|
|
||||||
public class Languages : List<Language>
|
public class Languages : List<Language>
|
||||||
{
|
{
|
||||||
public void Add(string longer, string shorter)
|
public void Add(string longer, string shorter)
|
||||||
|
@ -276,12 +280,12 @@ namespace OpenTXrecorder
|
||||||
description = words[1];
|
description = words[1];
|
||||||
voiceString = words[2].TrimEnd('\"', ',', ' ');
|
voiceString = words[2].TrimEnd('\"', ',', ' ');
|
||||||
path = dirPath;
|
path = dirPath;
|
||||||
fileExists = File.Exists(fullPath());
|
fileExists = File.Exists(fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string fullPath()
|
public string fullPath
|
||||||
{
|
{
|
||||||
return System.AppDomain.CurrentDomain.BaseDirectory + path + fileName + ".wav";
|
get { return System.AppDomain.CurrentDomain.BaseDirectory + path + fileName + ".wav"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string toRaw()
|
public string toRaw()
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="clsWaveProcessor.cs" />
|
||||||
<Compile Include="sentencetables.cs" />
|
<Compile Include="sentencetables.cs" />
|
||||||
<Compile Include="WaveIn.cs" />
|
<Compile Include="WaveIn.cs" />
|
||||||
<Compile Include="WaveNative.cs" />
|
<Compile Include="WaveNative.cs" />
|
||||||
|
|
|
@ -67,5 +67,5 @@ using System.Windows;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.2")]
|
[assembly: AssemblyVersion("0.3")]
|
||||||
[assembly: AssemblyFileVersion("0.2")]
|
[assembly: AssemblyFileVersion("0.3")]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/* This file is part of OpenTX Recorder.
|
||||||
* This is free software: you can redistribute it and/or modify
|
* OpenTX Recorder is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
* along with OpenTX Recorder. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Copyright 2014 Tomas Andersson */
|
* Copyright 2014 Tomas Andersson */
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ namespace WaveLib
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WavFileWriter
|
public class WavFileWriter
|
||||||
{
|
{
|
||||||
BinaryWriter filewriter;
|
BinaryWriter filewriter;
|
||||||
long audiobyteswritten;
|
long audiobyteswritten;
|
||||||
|
|
163
sound/recorder/clsWaveProcessor.cs
Normal file
163
sound/recorder/clsWaveProcessor.cs
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using WaveLib;
|
||||||
|
|
||||||
|
|
||||||
|
public class wavProcessor
|
||||||
|
{
|
||||||
|
public int Length;
|
||||||
|
public short Channels;
|
||||||
|
public int SampleRate;
|
||||||
|
public int DataLength;
|
||||||
|
public short BitsPerSample;
|
||||||
|
|
||||||
|
/// Filter out silence or noise from start and end of wave file.
|
||||||
|
public bool StripSilence(string strPath, int noiceLevel)
|
||||||
|
{
|
||||||
|
if (strPath == null) strPath = "";
|
||||||
|
if (strPath == "") return false;
|
||||||
|
|
||||||
|
wavProcessor wain = new wavProcessor();
|
||||||
|
wavProcessor waout = new wavProcessor();
|
||||||
|
|
||||||
|
waout.DataLength = waout.Length = 0;
|
||||||
|
|
||||||
|
if (!wain.WaveHeaderIN(@strPath)) return false;
|
||||||
|
|
||||||
|
waout.DataLength = wain.DataLength;
|
||||||
|
waout.Length = wain.Length;
|
||||||
|
|
||||||
|
waout.BitsPerSample = wain.BitsPerSample;
|
||||||
|
waout.Channels = wain.Channels;
|
||||||
|
waout.SampleRate = wain.SampleRate;
|
||||||
|
|
||||||
|
byte[] arrfile = GetWAVEData(strPath);
|
||||||
|
|
||||||
|
//check for silence
|
||||||
|
int startpos = 0;
|
||||||
|
int endpos = arrfile.Length - 1;
|
||||||
|
//At start
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int j = 0; j < arrfile.Length; j += 2)
|
||||||
|
{
|
||||||
|
short snd = ComplementToSigned(ref arrfile, j);
|
||||||
|
if (snd > (-1 * noiceLevel) && snd < noiceLevel) startpos = j;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.Write(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//At end
|
||||||
|
for (int k = arrfile.Length - 1; k >= 0; k -= 2)
|
||||||
|
{
|
||||||
|
short snd = ComplementToSigned(ref arrfile, k - 1);
|
||||||
|
if (snd > (-1 * noiceLevel) && snd < noiceLevel)
|
||||||
|
endpos = k;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startpos == endpos) return false;
|
||||||
|
if ((endpos - startpos) < 1) return false;
|
||||||
|
|
||||||
|
byte[] newarr = new byte[(endpos - startpos) + 1];
|
||||||
|
|
||||||
|
for (int ni = 0, m = startpos; m <= endpos; m++, ni++)
|
||||||
|
newarr[ni] = arrfile[m];
|
||||||
|
|
||||||
|
//write file
|
||||||
|
waout.DataLength = newarr.Length;
|
||||||
|
|
||||||
|
WavFileWriter wfWriter = new WavFileWriter(@strPath, wain.SampleRate, wain.BitsPerSample, wain.Channels);
|
||||||
|
wfWriter.Write(newarr);
|
||||||
|
wfWriter.Close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read the wave file header and store the key values in public variable.
|
||||||
|
/// Adapted from - Concatenation Wave Files using C# 2005 by By Ehab Mohamed Essa
|
||||||
|
/// URL - http://www.codeproject.com/useritems/Concatenation_Wave_Files.asp
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="strPath">The physical path of wave file incl. file name for reading</param>
|
||||||
|
/// <returns>True/False</returns>
|
||||||
|
private bool WaveHeaderIN(string strPath)
|
||||||
|
{
|
||||||
|
if (strPath == null) strPath = "";
|
||||||
|
if (strPath == "") return false;
|
||||||
|
|
||||||
|
FileStream fs = new FileStream(strPath, FileMode.Open, FileAccess.Read);
|
||||||
|
|
||||||
|
BinaryReader br = new BinaryReader(fs);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Length = (int)fs.Length - 8;
|
||||||
|
fs.Position = 22;
|
||||||
|
Channels = br.ReadInt16(); //1
|
||||||
|
fs.Position = 24;
|
||||||
|
SampleRate = br.ReadInt32(); //16000
|
||||||
|
fs.Position = 34;
|
||||||
|
BitsPerSample = br.ReadInt16(); //16
|
||||||
|
DataLength = (int)fs.Length - 44;
|
||||||
|
byte[] arrfile = new byte[fs.Length - 44];
|
||||||
|
fs.Position = 44;
|
||||||
|
fs.Read(arrfile, 0, arrfile.Length);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
br.Close();
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// In stereo wave format, samples are stored in 2's complement. For Mono, it's necessary to
|
||||||
|
/// convert those samples to their equivalent signed value. This method is used
|
||||||
|
/// by other public methods to equilibrate wave formats of different files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytArr">Sample data in array</param>
|
||||||
|
/// <param name="intPos">Array offset</param>
|
||||||
|
/// <returns>Mono value as signed short</returns>
|
||||||
|
private short ComplementToSigned(ref byte[] bytArr, int intPos) // 2's complement to normal signed value
|
||||||
|
{
|
||||||
|
short snd = BitConverter.ToInt16(bytArr, intPos);
|
||||||
|
if (snd != 0)
|
||||||
|
snd = Convert.ToInt16((~snd | 1));
|
||||||
|
return snd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read the WAVE file then position to DADA segment and return the chunk as byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="strWAVEPath">Path of WAVE file</param>
|
||||||
|
/// <returns>byte array</returns>
|
||||||
|
private byte[] GetWAVEData(string strWAVEPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileStream fs = new FileStream(@strWAVEPath, FileMode.Open, FileAccess.Read);
|
||||||
|
byte[] arrfile = new byte[fs.Length - 44];
|
||||||
|
fs.Position = 44;
|
||||||
|
fs.Read(arrfile, 0, arrfile.Length);
|
||||||
|
fs.Close();
|
||||||
|
return arrfile;
|
||||||
|
}
|
||||||
|
catch (IOException ioex)
|
||||||
|
{
|
||||||
|
throw ioex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // End of clsWaveProcessor class
|
Loading…
Add table
Add a link
Reference in a new issue