diff --git a/sound/recorder/MainWindow.xaml.cs b/sound/recorder/MainWindow.xaml.cs index df5d7976d..d940d0d97 100644 --- a/sound/recorder/MainWindow.xaml.cs +++ b/sound/recorder/MainWindow.xaml.cs @@ -208,7 +208,9 @@ namespace OpenTXrecorder wavProcessor processor = new wavProcessor(); int noiceLevel = (int)this.noiceLevelSlider.Value; - processor.StripSilence(sentence.fullPath, noiceLevel ); + processor.StripSilence(sentence.fullPath, noiceLevel); + processor.ToneIn(sentence.fullPath); + processor.ToneOut(sentence.fullPath); } private void DataArrived(IntPtr data, int size) diff --git a/sound/recorder/Properties/AssemblyInfo.cs b/sound/recorder/Properties/AssemblyInfo.cs index 6defc2da9..4300c6a81 100644 --- a/sound/recorder/Properties/AssemblyInfo.cs +++ b/sound/recorder/Properties/AssemblyInfo.cs @@ -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.3")] -[assembly: AssemblyFileVersion("0.3")] +[assembly: AssemblyVersion("0.4")] +[assembly: AssemblyFileVersion("0.4")] diff --git a/sound/recorder/clsWaveProcessor.cs b/sound/recorder/clsWaveProcessor.cs index da815f5a9..4ebef5fb2 100644 --- a/sound/recorder/clsWaveProcessor.cs +++ b/sound/recorder/clsWaveProcessor.cs @@ -13,48 +13,41 @@ public class wavProcessor public int DataLength; public short BitsPerSample; + /// /// Filter out silence or noise from start and end of wave file. + /// + /// Source wave file + /// Absolute value for noice threshold + /// True/False public bool StripSilence(string strPath, int noiceLevel) { - if (strPath == null) strPath = ""; - if (strPath == "") return false; + if ((strPath == null) || (strPath == "")) + return false; + // Read from file 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 + + // Check for silence at start + for (int j = 0; j < arrfile.Length; j += 2) { - 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); + short snd = ComplementToSigned(ref arrfile, j); + if (snd > (-1 * noiceLevel) && snd < noiceLevel) startpos = j; + else + break; } + // Allow room for tone-in buffer + int buffer = wain.SampleRate * (wain.BitsPerSample / 8) / 8; + startpos = startpos - buffer; + if (startpos < 0) + startpos = 0; - //At end + // Check foor silence at end for (int k = arrfile.Length - 1; k >= 0; k -= 2) { short snd = ComplementToSigned(ref arrfile, k - 1); @@ -63,6 +56,10 @@ public class wavProcessor else break; } + // Allow room for tone-out buffer + endpos = endpos + buffer; + if (endpos > (arrfile.Length - 1)) + endpos = arrfile.Length - 1; if (startpos == endpos) return false; if ((endpos - startpos) < 1) return false; @@ -73,7 +70,6 @@ public class wavProcessor newarr[ni] = arrfile[m]; // write file back - waout.DataLength = newarr.Length; WavFileWriter writer = new WavFileWriter(@strPath, wain.SampleRate, wain.BitsPerSample, wain.Channels); writer.Write(newarr, newarr.Length); writer.Close(); @@ -81,10 +77,82 @@ public class wavProcessor return true; } + /// + /// Tone in wav file + /// + /// Source wave + /// True/False + public bool ToneIn(string strPath) + { + if ((strPath == null) || (strPath == "")) + return false; + + // Read from file + wavProcessor wain = new wavProcessor(); + if (!wain.WaveHeaderIN(@strPath)) return false; + byte[] arrfile = GetWAVEData(strPath); + + // Calculate constants + int start = 0; + int end = wain.SampleRate * (wain.BitsPerSample / 8) / 8; // 0.125 seconds + int span = end - start; + + //change volume + for (int j = start; j < end; j += 2) + { + short snd = ComplementToSigned(ref arrfile, j); + snd = Convert.ToInt16(snd * (j / span)); + byte[] newval = SignedToComplement(snd); + arrfile[j] = newval[0]; + arrfile[j + 1] = newval[1]; + } + // write file back + WavFileWriter writer = new WavFileWriter(@strPath, wain.SampleRate, wain.BitsPerSample, wain.Channels); + writer.Write(arrfile, arrfile.Length); + writer.Close(); + + return true; + } + /// + /// Tone out wav file + /// + /// Source wave + /// True/False + public bool ToneOut(string strPath) + { + if ((strPath == null) || (strPath == "")) + return false; + + // Read from file + wavProcessor wain = new wavProcessor(); + if (!wain.WaveHeaderIN(@strPath)) return false; + byte[] arrfile = GetWAVEData(strPath); + + // Calculate constants + int end = wain.Length; + int start = end - (wain.SampleRate * (wain.BitsPerSample / 8) / 8); // 0.125 seconds from end + int span = end - start; + + //change volume + for (int j = start; j < arrfile.Length; j += 2) + { + short snd = ComplementToSigned(ref arrfile, j); + snd = Convert.ToInt16(snd * (end - j) / span); + + byte[] newval = SignedToComplement(snd); + arrfile[j] = newval[0]; + arrfile[j + 1] = newval[1]; + } + // write file back + WavFileWriter writer = new WavFileWriter(@strPath, wain.SampleRate, wain.BitsPerSample, wain.Channels); + writer.Write(arrfile, arrfile.Length); + writer.Close(); + + return true; + } + /// /// 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 /// /// The physical path of wave file incl. file name for reading /// True/False @@ -137,7 +205,19 @@ public class wavProcessor snd = Convert.ToInt16((~snd | 1)); return snd; } - + /// + /// Convert signed sample value back to 2's complement value equivalent to Stereo. This method is used + /// by other public methods to equilibrate wave formats of different files. + /// + /// The mono signed value as short + /// Stereo 2's complement value as byte array + private byte[] SignedToComplement(short shtVal) //Convert to 2's complement and return as byte array of 2 bytes + { + byte[] bt = new byte[2]; + shtVal = Convert.ToInt16((~shtVal | 1)); + bt = BitConverter.GetBytes(shtVal); + return bt; + } /// /// Read the WAVE file then position to DADA segment and return the chunk as byte array ///