1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-13 03:19:53 +03:00

Added audio processing of recorded files.

This commit is contained in:
Kjell Kernen 2014-03-22 00:38:18 +01:00
parent bc9650fc0c
commit cf22b2328b
6 changed files with 198 additions and 17 deletions

View file

@ -57,9 +57,7 @@
SelectionChanged="switchLanguage"
Width="200" Height="23" />
</StackPanel>
</StackPanel>
<Separator Height="5" />
<TextBlock Text="Sentence" Margin="5,0,0,0" FontSize="18" />
<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" />
<TextBox Text="{Binding Path=voiceString}" Grid.Row="2" Grid.Column="1" Margin="0,0,10,0"/>
</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 Name="btnRecord" ToolTip="Start recording" Click="record" Margin="20,0,0,0" >
<Image Height="32" Source="/OpenTXrecorder;component/record.png"/>

View file

@ -161,7 +161,7 @@ namespace OpenTXrecorder
{
try
{
SoundPlayer player = new SoundPlayer(sentence.fullPath());
SoundPlayer player = new SoundPlayer(sentence.fullPath);
player.Play();
}
catch (Exception) { }; // Catch and disregard all media exceptions
@ -180,7 +180,7 @@ namespace OpenTXrecorder
isRecording = true;
lblRecording.Visibility = System.Windows.Visibility.Visible;
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
System.IO.File.WriteAllText(path, ""); // Create and flush the file
@ -199,11 +199,16 @@ namespace OpenTXrecorder
recorder.Close();
filewriter.Close();
int index = this.lvSentences.SelectedIndex;
lblRecording.Visibility = System.Windows.Visibility.Hidden;
Sentence sentence = (Sentence)this.lvSentences.SelectedItem;
loadLanguage(); // Called to refresh the sentence data of the current langugae
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)
@ -235,10 +240,9 @@ namespace OpenTXrecorder
shortLanguage = str;
}
}
// Data container classes
/*
* Data container classes
*/
public class Languages : List<Language>
{
public void Add(string longer, string shorter)
@ -276,12 +280,12 @@ namespace OpenTXrecorder
description = words[1];
voiceString = words[2].TrimEnd('\"', ',', ' ');
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()

View file

@ -80,6 +80,7 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="clsWaveProcessor.cs" />
<Compile Include="sentencetables.cs" />
<Compile Include="WaveIn.cs" />
<Compile Include="WaveNative.cs" />

View file

@ -67,5 +67,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2")]
[assembly: AssemblyFileVersion("0.2")]
[assembly: AssemblyVersion("0.3")]
[assembly: AssemblyFileVersion("0.3")]

View file

@ -1,5 +1,5 @@
/*
* This is free software: you can redistribute it and/or modify
/* This file is part of OpenTX Recorder.
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
@ -10,7 +10,7 @@
* GNU General Public License for more details.
* 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 */
@ -91,7 +91,7 @@ namespace WaveLib
}
}
class WavFileWriter
public class WavFileWriter
{
BinaryWriter filewriter;
long audiobyteswritten;

View 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