mirror of
https://github.com/RPCS3/soundtouch.git
synced 2024-11-08 20:12:27 +01:00
Refactored C# interface & example
This commit is contained in:
parent
80281c8e1b
commit
05a3403137
37
README.html
37
README.html
@ -13,7 +13,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="normal">
|
<body class="normal">
|
||||||
<hr>
|
<hr>
|
||||||
<h1>SoundTouch audio processing library v2.0</h1>
|
<h1>SoundTouch audio processing library v2.0.1pre</h1>
|
||||||
<p class="normal">SoundTouch library Copyright © Olli Parviainen 2001-2017</p>
|
<p class="normal">SoundTouch library Copyright © Olli Parviainen 2001-2017</p>
|
||||||
<hr>
|
<hr>
|
||||||
<h2>1. Introduction </h2>
|
<h2>1. Introduction </h2>
|
||||||
@ -123,7 +123,7 @@ destination locations.</p>
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h4><b>2.2.1 Required GNU tools</b> </h4>
|
<h4><b>2.2.1 Required GNU tools</b></h4>
|
||||||
<p> <span style="font-weight: bold;">Bash shell</span>, <span
|
<p> <span style="font-weight: bold;">Bash shell</span>, <span
|
||||||
style="font-weight: bold;">GNU C++ compiler</span>, <span
|
style="font-weight: bold;">GNU C++ compiler</span>, <span
|
||||||
style="font-weight: bold;">libtool</span>, <span
|
style="font-weight: bold;">libtool</span>, <span
|
||||||
@ -222,7 +222,7 @@ as combination of two primary effects, <em>sample rate transposing</em>
|
|||||||
and <em>time-stretching</em>.</p>
|
and <em>time-stretching</em>.</p>
|
||||||
<p><em>Sample rate transposing</em> affects both the audio stream
|
<p><em>Sample rate transposing</em> affects both the audio stream
|
||||||
duration and pitch. It's implemented simply by converting the original
|
duration and pitch. It's implemented simply by converting the original
|
||||||
audio sample stream to the desired duration by interpolating from
|
audio sample stream to the desired duration by interpolating from
|
||||||
the original audio samples. In SoundTouch, linear interpolation with
|
the original audio samples. In SoundTouch, linear interpolation with
|
||||||
anti-alias filtering is used. Theoretically a higher-order
|
anti-alias filtering is used. Theoretically a higher-order
|
||||||
interpolation provide better result than 1st order linear
|
interpolation provide better result than 1st order linear
|
||||||
@ -271,7 +271,7 @@ length of a single processing sequence in milliseconds which determines
|
|||||||
the how the original sound is chopped in the time-stretch algorithm.
|
the how the original sound is chopped in the time-stretch algorithm.
|
||||||
Larger values mean fewer sequences are used in processing. In principle
|
Larger values mean fewer sequences are used in processing. In principle
|
||||||
a larger value sounds better when slowing down the tempo, but worse
|
a larger value sounds better when slowing down the tempo, but worse
|
||||||
when increasing the tempo and vice versa. <br>
|
when increasing the tempo and vice versa.<br>
|
||||||
<br>
|
<br>
|
||||||
By default, this setting value is calculated automatically according to
|
By default, this setting value is calculated automatically according to
|
||||||
tempo value.<br>
|
tempo value.<br>
|
||||||
@ -280,7 +280,7 @@ tempo value.<br>
|
|||||||
default length in milliseconds is for the algorithm that seeks the best
|
default length in milliseconds is for the algorithm that seeks the best
|
||||||
possible overlapping location. This determines from how wide a sample
|
possible overlapping location. This determines from how wide a sample
|
||||||
"window" the algorithm can use to find an optimal mixing location when
|
"window" the algorithm can use to find an optimal mixing location when
|
||||||
the sound sequences are to be linked back together. <br>
|
the sound sequences are to be linked back together.<br>
|
||||||
<br>
|
<br>
|
||||||
The bigger this window setting is, the higher the possibility to find a
|
The bigger this window setting is, the higher the possibility to find a
|
||||||
better mixing position becomes, but at the same time large values may
|
better mixing position becomes, but at the same time large values may
|
||||||
@ -348,7 +348,7 @@ computation burden</td>
|
|||||||
</td>
|
</td>
|
||||||
<td valign="top">Default value is relatively large, chosen to
|
<td valign="top">Default value is relatively large, chosen to
|
||||||
suit with above parameters.</td>
|
suit with above parameters.</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top"></td>
|
||||||
<td valign="top">If you reduce the "sequence ms" setting, you
|
<td valign="top">If you reduce the "sequence ms" setting, you
|
||||||
might wish to try a smaller value.</td>
|
might wish to try a smaller value.</td>
|
||||||
<td valign="top">Increasing the parameter value increases
|
<td valign="top">Increasing the parameter value increases
|
||||||
@ -361,7 +361,7 @@ computation burden</td>
|
|||||||
<p>The time-stretch routine has a 'quick' mode that substantially
|
<p>The time-stretch routine has a 'quick' mode that substantially
|
||||||
speeds up the algorithm but may slightly compromise the sound quality.
|
speeds up the algorithm but may slightly compromise the sound quality.
|
||||||
This mode is activated by calling SoundTouch::setSetting()
|
This mode is activated by calling SoundTouch::setSetting()
|
||||||
function with parameter id of SETTING_USE_QUICKSEEK and value
|
function with parameter id of SETTING_USE_QUICKSEEK and value
|
||||||
"1", i.e. </p>
|
"1", i.e. </p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>setSetting(SETTING_USE_QUICKSEEK, 1);</p>
|
<p>setSetting(SETTING_USE_QUICKSEEK, 1);</p>
|
||||||
@ -445,13 +445,13 @@ file format). Give "stdin" as filename to use standard input pipe. </td>
|
|||||||
</td>
|
</td>
|
||||||
<td valign="top">Name of the output sound file where the
|
<td valign="top">Name of the output sound file where the
|
||||||
resulting sound is saved (in .WAV audio file format). This parameter
|
resulting sound is saved (in .WAV audio file format). This parameter
|
||||||
may be omitted if you don't want to save the output (e.g. when
|
may be omitted if you don't want to save the output (e.g. when
|
||||||
only calculating BPM rate with '-bpm' switch). Give "stdout" as
|
only calculating BPM rate with '-bpm' switch). Give "stdout" as
|
||||||
filename to use standard output pipe.</td>
|
filename to use standard output pipe.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<pre> [switches]</pre>
|
<pre>[switches]</pre>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">Are one or more control switches.</td>
|
<td valign="top">Are one or more control switches.</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -575,10 +575,11 @@ this corresponds to lowering the pitch by -0.318 semitones:</p>
|
|||||||
<h3>5.1. SoundTouch library Change History </h3>
|
<h3>5.1. SoundTouch library Change History </h3>
|
||||||
<p><b>2.0.1pre:</b></p>
|
<p><b>2.0.1pre:</b></p>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>Refactored C# interface example</li>
|
||||||
<li>Disable anti-alias filter when switch
|
<li>Disable anti-alias filter when switch
|
||||||
SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER defined because anti-alias
|
SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER defined because anti-alias
|
||||||
filter cause slight click if the rate change crosses zero during
|
filter cause slight click if the rate change crosses zero during
|
||||||
processing</li>
|
processing</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><b>2.0:</b></p>
|
<p><b>2.0:</b></p>
|
||||||
<ul>
|
<ul>
|
||||||
@ -670,13 +671,13 @@ sample batch sizes</li>
|
|||||||
<ul>
|
<ul>
|
||||||
<li> Added normalization to correlation calculation and improvement
|
<li> Added normalization to correlation calculation and improvement
|
||||||
automatic seek/sequence parameter calculation to improve sound quality</li>
|
automatic seek/sequence parameter calculation to improve sound quality</li>
|
||||||
<li> Bugfixes:
|
<li> Bugfixes:
|
||||||
<ul>
|
<ul>
|
||||||
<li> Fixed negative array indexing in quick seek algorithm</li>
|
<li> Fixed negative array indexing in quick seek algorithm</li>
|
||||||
<li> FIR autoalias filter running too far in processing buffer</li>
|
<li> FIR autoalias filter running too far in processing buffer</li>
|
||||||
<li> Check against zero sample count in rate transposing</li>
|
<li> Check against zero sample count in rate transposing</li>
|
||||||
<li> Fix for x86-64 support: Removed pop/push instructions from
|
<li> Fix for x86-64 support: Removed pop/push instructions from
|
||||||
the cpu detection algorithm. </li>
|
the cpu detection algorithm.</li>
|
||||||
<li> Check against empty buffers in FIFOSampleBuffer</li>
|
<li> Check against empty buffers in FIFOSampleBuffer</li>
|
||||||
<li> Other minor fixes & code cleanup</li>
|
<li> Other minor fixes & code cleanup</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -692,7 +693,7 @@ negative side or vice versa</li>
|
|||||||
<p><strong>1.4.1:</strong></p>
|
<p><strong>1.4.1:</strong></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li> Fixed a buffer overflow bug in BPM detect algorithm routines if
|
<li> Fixed a buffer overflow bug in BPM detect algorithm routines if
|
||||||
processing more than 2048 samples at one call </li>
|
processing more than 2048 samples at one call</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><strong>1.4.0:</strong></p>
|
<p><strong>1.4.0:</strong></p>
|
||||||
<ul>
|
<ul>
|
||||||
@ -775,7 +776,6 @@ accessing the FIFOSampleBuffer class from external files.</li>
|
|||||||
<ul>
|
<ul>
|
||||||
<li> Initial release</li>
|
<li> Initial release</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p> </p>
|
|
||||||
<h3>5.2. SoundStretch application Change History </h3>
|
<h3>5.2. SoundStretch application Change History </h3>
|
||||||
<p><b>1.9:</b></p>
|
<p><b>1.9:</b></p>
|
||||||
<ul>
|
<ul>
|
||||||
@ -862,7 +862,7 @@ submitted bugfixes:</p>
|
|||||||
<li> Jason Garland</li>
|
<li> Jason Garland</li>
|
||||||
<li> Takashi Iwai</li>
|
<li> Takashi Iwai</li>
|
||||||
<li> Thomas Klausner</li>
|
<li> Thomas Klausner</li>
|
||||||
<li> Lu Zhihe</li>
|
<li> Lu Zhihe</li>
|
||||||
<li> Tony Mechelynck </li>
|
<li> Tony Mechelynck </li>
|
||||||
<li> Mathias Möhl</li>
|
<li> Mathias Möhl</li>
|
||||||
<li> Yuval Naveh</li>
|
<li> Yuval Naveh</li>
|
||||||
@ -879,8 +879,9 @@ submitted bugfixes:</p>
|
|||||||
<li> Albert Sirvent</li>
|
<li> Albert Sirvent</li>
|
||||||
<li> Tyson Smith</li>
|
<li> Tyson Smith</li>
|
||||||
<li> John Stumpo</li>
|
<li> John Stumpo</li>
|
||||||
|
<li> Mario di Vece</li>
|
||||||
<li> Katja Vetter</li>
|
<li> Katja Vetter</li>
|
||||||
<li> Wu Q.</li>
|
<li> Wu Q.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Moral greetings to all other contributors and users also!</p>
|
<p>Moral greetings to all other contributors and users also!</p>
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:csharp_example"
|
xmlns:local="clr-namespace:csharp_example"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="C# SoundTouch example" Height="250 " Width="400">
|
Title="C# SoundTouch example" Height="250" Width="400" AllowDrop="True" Drop="Window_Drop">
|
||||||
<Grid Margin="0,0,0,-3">
|
<Grid Margin="0,0,0,-3">
|
||||||
<TextBlock HorizontalAlignment="Left" Margin="10,21,0,0" Text="Input audio file:" VerticalAlignment="Top"/>
|
<TextBlock HorizontalAlignment="Left" Margin="10,21,0,0" Text="Input audio file:" VerticalAlignment="Top"/>
|
||||||
<TextBox x:Name="textBox_filename" Height="23" Margin="107,20,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="180" IsEnabled="False"/>
|
<TextBox x:Name="textBox_filename" Height="23" Margin="107,20,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="180" IsEnabled="False"/>
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
using soundtouch;
|
using soundtouch;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@ -45,7 +46,7 @@ namespace csharp_example
|
|||||||
string status;
|
string status;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
status = String.Format("SoundTouch version: {0}", SoundTouch.GetVersionString());
|
status = String.Format("SoundTouch version: {0}", SoundTouch.Version);
|
||||||
}
|
}
|
||||||
catch (Exception exp)
|
catch (Exception exp)
|
||||||
{
|
{
|
||||||
@ -61,27 +62,44 @@ namespace csharp_example
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Open mp3 file for playback
|
||||||
|
private void OpenFile(string fileName)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
if (processor.OpenMp3File(fileName) == true)
|
||||||
|
{
|
||||||
|
textBox_filename.Text = fileName;
|
||||||
|
button_play.IsEnabled = true;
|
||||||
|
button_stop.IsEnabled = true;
|
||||||
|
|
||||||
|
// Parse adjustment settings
|
||||||
|
ParseTempoTextBox();
|
||||||
|
ParsePitchTextBox();
|
||||||
|
ParseRateTextBox();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textBox_filename.Text = "";
|
||||||
|
button_play.IsEnabled = false;
|
||||||
|
button_stop.IsEnabled = false;
|
||||||
|
MessageBox.Show("Coudln't open audio file " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void button_browse_Click(object sender, RoutedEventArgs e)
|
private void button_browse_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
// Show file selection dialog
|
||||||
Microsoft.Win32.OpenFileDialog openDialog = new Microsoft.Win32.OpenFileDialog();
|
Microsoft.Win32.OpenFileDialog openDialog = new Microsoft.Win32.OpenFileDialog();
|
||||||
|
if (string.IsNullOrEmpty(textBox_filename.Text) == false)
|
||||||
|
{
|
||||||
|
// if an audio file is open, set directory to same as with the file
|
||||||
|
openDialog.InitialDirectory = Path.GetDirectoryName(textBox_filename.Text);
|
||||||
|
}
|
||||||
openDialog.Filter = "MP3 files (*.mp3)|*.mp3";
|
openDialog.Filter = "MP3 files (*.mp3)|*.mp3";
|
||||||
if (openDialog.ShowDialog() == true)
|
if (openDialog.ShowDialog() == true)
|
||||||
{
|
{
|
||||||
if (processor.OpenMp3File(openDialog.FileName) == true)
|
OpenFile(openDialog.FileName);
|
||||||
{
|
|
||||||
textBox_filename.Text = openDialog.FileName;
|
|
||||||
button_play.IsEnabled = true;
|
|
||||||
button_stop.IsEnabled = true;
|
|
||||||
|
|
||||||
// Parse adjustment settings
|
|
||||||
ParseTempoTextBox();
|
|
||||||
ParsePitchTextBox();
|
|
||||||
ParseRateTextBox();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("Coudln't open audio file " + openDialog.FileName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +123,7 @@ namespace csharp_example
|
|||||||
|
|
||||||
private void button_play_Click(object sender, RoutedEventArgs e)
|
private void button_play_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (button_play.Content == "_Pause")
|
if ((string)button_play.Content == "_Pause")
|
||||||
{
|
{
|
||||||
// Pause
|
// Pause
|
||||||
if (processor.Pause())
|
if (processor.Pause())
|
||||||
@ -126,7 +144,7 @@ namespace csharp_example
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void button_stop_Click(object sender, RoutedEventArgs e)
|
private void Stop()
|
||||||
{
|
{
|
||||||
if (processor.Stop())
|
if (processor.Stop())
|
||||||
{
|
{
|
||||||
@ -136,6 +154,12 @@ namespace csharp_example
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void button_stop_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool parse_percentValue(TextBox box, out double value)
|
private bool parse_percentValue(TextBox box, out double value)
|
||||||
{
|
{
|
||||||
if (double.TryParse(box.Text, out value) == false) return false;
|
if (double.TryParse(box.Text, out value) == false) return false;
|
||||||
@ -150,7 +174,7 @@ namespace csharp_example
|
|||||||
double pitchValue;
|
double pitchValue;
|
||||||
if (double.TryParse(textBox_pitch.Text, out pitchValue))
|
if (double.TryParse(textBox_pitch.Text, out pitchValue))
|
||||||
{
|
{
|
||||||
if (processor.streamProcessor != null) processor.streamProcessor.st.SetPitchSemiTones((float)pitchValue);
|
if (processor.streamProcessor != null) processor.streamProcessor.st.PitchSemiTones = (float)pitchValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +184,7 @@ namespace csharp_example
|
|||||||
double tempoValue;
|
double tempoValue;
|
||||||
if (parse_percentValue(textBox_tempo, out tempoValue))
|
if (parse_percentValue(textBox_tempo, out tempoValue))
|
||||||
{
|
{
|
||||||
if (processor.streamProcessor != null) processor.streamProcessor.st.SetTempoChange((float)tempoValue);
|
if (processor.streamProcessor != null) processor.streamProcessor.st.TempoChange = (float)tempoValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +194,7 @@ namespace csharp_example
|
|||||||
double rateValue;
|
double rateValue;
|
||||||
if (parse_percentValue(textBox_rate, out rateValue))
|
if (parse_percentValue(textBox_rate, out rateValue))
|
||||||
{
|
{
|
||||||
if (processor.streamProcessor != null) processor.streamProcessor.st.SetRateChange((float)rateValue);
|
if (processor.streamProcessor != null) processor.streamProcessor.st.RateChange = (float)rateValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,5 +245,14 @@ namespace csharp_example
|
|||||||
ParseRateTextBox();
|
ParseRateTextBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Handler for file drag & drop over the window
|
||||||
|
private void Window_Drop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||||
|
// open 1st of the chosen files
|
||||||
|
OpenFile(files[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,8 @@ namespace csharp_example
|
|||||||
{
|
{
|
||||||
inputStr = input;
|
inputStr = input;
|
||||||
st = new SoundTouch();
|
st = new SoundTouch();
|
||||||
st.SetChannels((uint)input.WaveFormat.Channels);
|
st.Channels = (uint)input.WaveFormat.Channels;
|
||||||
st.SetSampleRate((uint)input.WaveFormat.SampleRate);
|
st.SampleRate = (uint)input.WaveFormat.SampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -123,7 +123,7 @@ namespace csharp_example
|
|||||||
// Iterate until enough samples available for output:
|
// Iterate until enough samples available for output:
|
||||||
// - read samples from input stream
|
// - read samples from input stream
|
||||||
// - put samples to SoundStretch processor
|
// - put samples to SoundStretch processor
|
||||||
while (st.NumSamples() < count)
|
while (st.AvailableSampleCount < count)
|
||||||
{
|
{
|
||||||
int nbytes = inputStr.Read(bytebuffer, 0, bytebuffer.Length);
|
int nbytes = inputStr.Read(bytebuffer, 0, bytebuffer.Length);
|
||||||
if (nbytes == 0)
|
if (nbytes == 0)
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
/// Author e-mail : oparviai 'at' iki.fi
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
///
|
///
|
||||||
|
/// The C# wrapper improved by Mario Di Vece
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// License :
|
// License :
|
||||||
@ -34,37 +36,341 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace soundtouch
|
namespace soundtouch
|
||||||
{
|
{
|
||||||
public class SoundTouch
|
public sealed class SoundTouch : IDisposable
|
||||||
{
|
{
|
||||||
|
#region Private Members
|
||||||
|
|
||||||
|
private const string SoundTouchLibrary = "SoundTouch.dll";
|
||||||
|
private readonly object SyncRoot = new object();
|
||||||
|
private bool IsDisposed = false;
|
||||||
private IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SoundTouch"/> class.
|
||||||
|
/// </summary>
|
||||||
public SoundTouch()
|
public SoundTouch()
|
||||||
{
|
{
|
||||||
handle = soundtouch_createInstance();
|
handle = NativeMethods.CreateInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="SoundTouch"/> class.
|
||||||
|
/// </summary>
|
||||||
~SoundTouch()
|
~SoundTouch()
|
||||||
{
|
{
|
||||||
soundtouch_destroyInstance(handle);
|
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||||
|
Dispose(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Settings as defined in SoundTouch.h
|
||||||
|
/// </summary>
|
||||||
|
public enum Setting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enable/disable anti-alias filter in pitch transposer (0 = disable)
|
||||||
|
/// </summary>
|
||||||
|
UseAntiAliasFilter = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pitch transposer anti-alias filter length (8 .. 128 taps, default = 32)
|
||||||
|
/// </summary>
|
||||||
|
AntiAliasFilterLength = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable/disable quick seeking algorithm in tempo changer routine
|
||||||
|
/// (enabling quick seeking lowers CPU utilization but causes a minor sound
|
||||||
|
/// quality compromising)
|
||||||
|
/// </summary>
|
||||||
|
UseQuickSeek = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Time-stretch algorithm single processing sequence length in milliseconds. This determines
|
||||||
|
/// to how long sequences the original sound is chopped in the time-stretch algorithm.
|
||||||
|
/// See "STTypes.h" or README for more information.
|
||||||
|
/// </summary>
|
||||||
|
SequenceMilliseconds = 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the
|
||||||
|
/// best possible overlapping location. This determines from how wide window the algorithm
|
||||||
|
/// may look for an optimal joining location when mixing the sound sequences back together.
|
||||||
|
/// See "STTypes.h" or README for more information.
|
||||||
|
/// </summary>
|
||||||
|
SeekWindowMilliseconds = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences
|
||||||
|
/// are mixed back together, to form a continuous sound stream, this parameter defines over
|
||||||
|
/// how long period the two consecutive sequences are let to overlap each other.
|
||||||
|
/// See "STTypes.h" or README for more information.
|
||||||
|
/// </summary>
|
||||||
|
OverlapMilliseconds = 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call "getSetting" with this ID to query processing sequence size in samples.
|
||||||
|
/// This value gives approximate value of how many input samples you'll need to
|
||||||
|
/// feed into SoundTouch after initial buffering to get out a new batch of
|
||||||
|
/// output samples.
|
||||||
|
///
|
||||||
|
/// This value does not include initial buffering at beginning of a new processing
|
||||||
|
/// stream, use SETTING_INITIAL_LATENCY to get the initial buffering size.
|
||||||
|
///
|
||||||
|
/// Notices:
|
||||||
|
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
||||||
|
/// - This parameter value is not constant but change depending on
|
||||||
|
/// tempo/pitch/rate/samplerate settings.
|
||||||
|
/// </summary>
|
||||||
|
NominalInputSequence = 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call "getSetting" with this ID to query nominal average processing output
|
||||||
|
/// size in samples. This value tells approcimate value how many output samples
|
||||||
|
/// SoundTouch outputs once it does DSP processing run for a batch of input samples.
|
||||||
|
///
|
||||||
|
/// Notices:
|
||||||
|
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
||||||
|
/// - This parameter value is not constant but change depending on
|
||||||
|
/// tempo/pitch/rate/samplerate settings.
|
||||||
|
/// </summary>
|
||||||
|
NominalOutputSequence = 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call "getSetting" with this ID to query initial processing latency, i.e.
|
||||||
|
/// approx. how many samples you'll need to enter to SoundTouch pipeline before
|
||||||
|
/// you can expect to get first batch of ready output samples out.
|
||||||
|
///
|
||||||
|
/// After the first output batch, you can then expect to get approx.
|
||||||
|
/// SETTING_NOMINAL_OUTPUT_SEQUENCE ready samples out for every
|
||||||
|
/// SETTING_NOMINAL_INPUT_SEQUENCE samples that you enter into SoundTouch.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// processing with parameter -tempo=5
|
||||||
|
/// => initial latency = 5509 samples
|
||||||
|
/// input sequence = 4167 samples
|
||||||
|
/// output sequence = 3969 samples
|
||||||
|
///
|
||||||
|
/// Accordingly, you can expect to feed in approx. 5509 samples at beginning of
|
||||||
|
/// the stream, and then you'll get out the first 3969 samples. After that, for
|
||||||
|
/// every approx. 4167 samples that you'll put in, you'll receive again approx.
|
||||||
|
/// 3969 samples out.
|
||||||
|
///
|
||||||
|
/// This also means that average latency during stream processing is
|
||||||
|
/// INITIAL_LATENCY-OUTPUT_SEQUENCE/2, in the above example case 5509-3969/2
|
||||||
|
/// = 3524 samples
|
||||||
|
///
|
||||||
|
/// Notices:
|
||||||
|
/// - This is read-only parameter, i.e. setSetting ignores this parameter
|
||||||
|
/// - This parameter value is not constant but change depending on
|
||||||
|
/// tempo/pitch/rate/samplerate settings.
|
||||||
|
/// </summary>
|
||||||
|
InitialLatency = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get SoundTouch version string
|
/// Get SoundTouch version string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static String GetVersionString()
|
public static string Version
|
||||||
{
|
{
|
||||||
// convert "char *" data to c# string
|
get
|
||||||
return Marshal.PtrToStringAnsi(soundtouch_getVersionString());
|
{
|
||||||
|
// convert "char *" data to c# string
|
||||||
|
return Marshal.PtrToStringAnsi(NativeMethods.GetVersionString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the SoundTouch Library (dll) is available
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsAvailable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var versionId = NativeMethods.GetVersionId();
|
||||||
|
return versionId != 0;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns number of processed samples currently available in SoundTouch for immediate output.
|
/// Returns number of processed samples currently available in SoundTouch for immediate output.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint NumSamples()
|
public uint AvailableSampleCount
|
||||||
{
|
{
|
||||||
return soundtouch_numSamples(handle);
|
get { lock (SyncRoot) { return NativeMethods.NumSamples(handle); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns number of samples currently unprocessed in SoundTouch internal buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Number of sample frames</returns>
|
||||||
|
public uint UnprocessedSampleCount
|
||||||
|
{
|
||||||
|
get { lock (SyncRoot) { return NativeMethods.NumUnprocessedSamples(handle); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if there aren't any samples available for outputting.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>nonzero if there aren't any samples available for outputting</returns>
|
||||||
|
public int IsEmpty
|
||||||
|
{
|
||||||
|
get { lock (SyncRoot) { return NativeMethods.IsEmpty(handle); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the number of channels
|
||||||
|
///
|
||||||
|
/// Value: 1 = mono, 2 = stereo, n = multichannel
|
||||||
|
/// </summary>
|
||||||
|
public uint Channels
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetChannels(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets sample rate.
|
||||||
|
/// Value: Sample rate, e.g. 44100
|
||||||
|
/// </summary>
|
||||||
|
public uint SampleRate
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetSampleRate(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets new tempo control value.
|
||||||
|
///
|
||||||
|
/// Value: Tempo setting. Normal tempo = 1.0, smaller values
|
||||||
|
/// represent slower tempo, larger faster tempo.
|
||||||
|
/// </summary>
|
||||||
|
public float Tempo
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetTempo(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets new tempo control value as a difference in percents compared
|
||||||
|
/// to the original tempo (-50 .. +100 %);
|
||||||
|
/// </summary>
|
||||||
|
public float TempoChange
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetTempoChange(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets new rate control value.
|
||||||
|
/// Rate setting. Normal rate = 1.0, smaller values
|
||||||
|
/// represent slower rate, larger faster rate.
|
||||||
|
/// </summary>
|
||||||
|
public float Rate
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetTempo(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets new rate control value as a difference in percents compared
|
||||||
|
/// to the original rate (-50 .. +100 %);
|
||||||
|
///
|
||||||
|
/// Value: Rate setting is in %
|
||||||
|
/// </summary>
|
||||||
|
public float RateChange
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetRateChange(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets new pitch control value.
|
||||||
|
///
|
||||||
|
/// Value: Pitch setting. Original pitch = 1.0, smaller values
|
||||||
|
/// represent lower pitches, larger values higher pitch.
|
||||||
|
/// </summary>
|
||||||
|
public float Pitch
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetPitch(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets pitch change in octaves compared to the original pitch
|
||||||
|
/// (-1.00 .. +1.00 for +- one octave);
|
||||||
|
///
|
||||||
|
/// Value: Pitch setting in octaves
|
||||||
|
/// </summary>
|
||||||
|
public float PitchOctaves
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetPitchOctaves(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets pitch change in semi-tones compared to the original pitch
|
||||||
|
/// (-12 .. +12 for +- one octave);
|
||||||
|
///
|
||||||
|
/// Value: Pitch setting in semitones
|
||||||
|
/// </summary>
|
||||||
|
public float PitchSemiTones
|
||||||
|
{
|
||||||
|
set { lock (SyncRoot) { NativeMethods.SetPitchSemiTones(handle, value); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes or gets a setting controlling the processing system behaviour. See the
|
||||||
|
/// 'SETTING_...' defines for available setting ID's.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The <see cref="System.Int32"/>.
|
||||||
|
/// </value>
|
||||||
|
/// <param name="settingId">The setting identifier.</param>
|
||||||
|
/// <returns>The value of the setting</returns>
|
||||||
|
public int this[Setting settingId]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (SyncRoot) { return NativeMethods.GetSetting(handle, (int)settingId); }
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
lock (SyncRoot) { NativeMethods.SetSetting(handle, (int)settingId, value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Sample Stream Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flushes the last samples from the processing pipeline to the output.
|
||||||
|
/// Clears also the internal processing buffers.
|
||||||
|
///
|
||||||
|
/// Note: This function is meant for extracting the last samples of a sound
|
||||||
|
/// stream. This function may introduce additional blank samples in the end
|
||||||
|
/// of the sound stream, and thus it's not recommended to call this function
|
||||||
|
/// in the middle of a sound stream.
|
||||||
|
/// </summary>
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
lock (SyncRoot) { NativeMethods.Flush(handle); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all the samples in the object's output and internal processing
|
||||||
|
/// buffers.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock (SyncRoot) { NativeMethods.Clear(handle); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -78,274 +384,161 @@ namespace soundtouch
|
|||||||
/// data for all channels</param>
|
/// data for all channels</param>
|
||||||
public void PutSamples(float[] samples, uint numSamples)
|
public void PutSamples(float[] samples, uint numSamples)
|
||||||
{
|
{
|
||||||
soundtouch_putSamples(handle, samples, numSamples);
|
lock (SyncRoot) { NativeMethods.PutSamples(handle, samples, numSamples); }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the number of channels
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="numChannels">1 = mono, 2 = stereo, n = multichannel</param>
|
|
||||||
public void SetChannels(uint numChannels)
|
|
||||||
{
|
|
||||||
soundtouch_setChannels(handle, numChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets sample rate.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="srate">Samplerate, e.g. 44100</param>
|
|
||||||
public void SetSampleRate(uint srate)
|
|
||||||
{
|
|
||||||
soundtouch_setSampleRate(handle, srate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Receive processed samples from the processor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="outBuffer">Buffer where to copy output samples</param>
|
|
||||||
/// <param name="maxSamples">Max number of sample frames to receive</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public uint ReceiveSamples(float[] outBuffer, uint maxSamples)
|
|
||||||
{
|
|
||||||
return soundtouch_receiveSamples(handle, outBuffer, maxSamples);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flushes the last samples from the processing pipeline to the output.
|
/// int16 version of putSamples(): This accept int16 (short) sample data
|
||||||
/// Clears also the internal processing buffers.
|
|
||||||
//
|
|
||||||
/// Note: This function is meant for extracting the last samples of a sound
|
|
||||||
/// stream. This function may introduce additional blank samples in the end
|
|
||||||
/// of the sound stream, and thus it's not recommended to call this function
|
|
||||||
/// in the middle of a sound stream.
|
|
||||||
/// </summary>
|
|
||||||
public void Flush()
|
|
||||||
{
|
|
||||||
soundtouch_flush(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clears all the samples in the object's output and internal processing
|
|
||||||
/// buffers.
|
|
||||||
/// </summary>
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
soundtouch_clear(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets new tempo control value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newTempo">Tempo setting. Normal tempo = 1.0, smaller values
|
|
||||||
/// represent slower tempo, larger faster tempo.</param>
|
|
||||||
public void SetTempo(float newTempo)
|
|
||||||
{
|
|
||||||
soundtouch_setTempo(handle, newTempo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets new tempo control value as a difference in percents compared
|
|
||||||
/// to the original tempo (-50 .. +100 %);
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newTempo">Tempo setting in %</param>
|
|
||||||
public void SetTempoChange(float newTempo)
|
|
||||||
{
|
|
||||||
soundtouch_setTempoChange(handle, newTempo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets new rate control value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newRate">Rate setting. Normal rate = 1.0, smaller values
|
|
||||||
/// represent slower rate, larger faster rate.</param>
|
|
||||||
public void SetRate(float newRate)
|
|
||||||
{
|
|
||||||
soundtouch_setTempo(handle, newRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets new rate control value as a difference in percents compared
|
|
||||||
/// to the original rate (-50 .. +100 %);
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newRate">Rate setting in %</param>
|
|
||||||
public void SetRateChange(float newRate)
|
|
||||||
{
|
|
||||||
soundtouch_setRateChange(handle, newRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets new pitch control value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newPitch">Pitch setting. Original pitch = 1.0, smaller values
|
|
||||||
/// represent lower pitches, larger values higher pitch.</param>
|
|
||||||
public void SetPitch(float newPitch)
|
|
||||||
{
|
|
||||||
soundtouch_setPitch(handle, newPitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets pitch change in octaves compared to the original pitch
|
|
||||||
/// (-1.00 .. +1.00 for +- one octave);
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newPitch">Pitch setting in octaves</param>
|
|
||||||
public void SetPitchOctaves(float newPitch)
|
|
||||||
{
|
|
||||||
soundtouch_setPitchOctaves(handle, newPitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets pitch change in semi-tones compared to the original pitch
|
|
||||||
/// (-12 .. +12 for +- one octave);
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newPitch">Pitch setting in semitones</param>
|
|
||||||
public void SetPitchSemiTones(float newPitch)
|
|
||||||
{
|
|
||||||
soundtouch_setPitchSemiTones(handle, newPitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// int16 version of soundtouch_putSamples(): This accept int16 (short) sample data
|
|
||||||
/// and internally converts it to float format before processing
|
/// and internally converts it to float format before processing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="samples">Sample input buffer.</param>
|
/// <param name="samples">Sample input buffer.</param>
|
||||||
/// <param name="numSamples">Number of sample frames in buffer. Notice
|
/// <param name="numSamples">Number of sample frames in buffer. Notice
|
||||||
/// that in case of multi-channel sound a single
|
/// that in case of multi-channel sound a single
|
||||||
/// sample frame contains data for all channels.</param>
|
/// sample frame contains data for all channels.</param>
|
||||||
public void PutSamples_i16(short[] samples, uint numSamples)
|
public void PutSamplesI16(short[] samples, uint numSamples)
|
||||||
{
|
{
|
||||||
soundtouch_putSamples_i16(handle, samples, numSamples);
|
lock (SyncRoot) { NativeMethods.PutSamples_i16(handle, samples, numSamples); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes a setting controlling the processing system behaviour. See the
|
/// Receive processed samples from the processor.
|
||||||
/// 'SETTING_...' defines for available setting ID's.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settingId">Setting ID number. see SETTING_... defines.</param>
|
/// <param name="outBuffer">Buffer where to copy output samples</param>
|
||||||
/// <param name="value"New setting value></param>
|
/// <param name="maxSamples">Max number of sample frames to receive</param>
|
||||||
/// <returns>nonzero if successful, otherwise zero</returns>
|
/// <returns>The number of samples received</returns>
|
||||||
public int SetSetting(int settingId, int value)
|
public uint ReceiveSamples(float[] outBuffer, uint maxSamples)
|
||||||
{
|
{
|
||||||
return soundtouch_setSetting(handle, settingId, value);
|
lock (SyncRoot) { return NativeMethods.ReceiveSamples(handle, outBuffer, maxSamples); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a setting controlling the processing system behaviour. See the
|
/// int16 version of receiveSamples(): This converts internal float samples
|
||||||
/// 'SETTING_...' defines for available setting ID's.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="settingId">Setting ID number</param>
|
|
||||||
/// <returns>The setting value</returns>
|
|
||||||
public int soundtouch_getSetting(int settingId)
|
|
||||||
{
|
|
||||||
return soundtouch_getSetting(handle, settingId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns number of samples currently unprocessed in SoundTouch internal buffer
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Number of sample frames</returns>
|
|
||||||
public uint NumUnprocessedSamples()
|
|
||||||
{
|
|
||||||
return soundtouch_numUnprocessedSamples(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// int16 version of soundtouch_receiveSamples(): This converts internal float samples
|
|
||||||
/// into int16 (short) return data type
|
/// into int16 (short) return data type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="outBuffer">Buffer where to copy output samples.</param>
|
/// <param name="outBuffer">Buffer where to copy output samples.</param>
|
||||||
/// <param name="maxSamples">How many samples to receive at max.</param>
|
/// <param name="maxSamples">How many samples to receive at max.</param>
|
||||||
/// <returns>Number of received sample frames</returns>
|
/// <returns>Number of received sample frames</returns>
|
||||||
public uint soundtouch_receiveSamples_i16(short[] outBuffer, uint maxSamples)
|
public uint ReceiveSamplesI16(short[] outBuffer, uint maxSamples)
|
||||||
{
|
{
|
||||||
return soundtouch_receiveSamples_i16(handle, outBuffer, maxSamples);
|
lock (SyncRoot) { return NativeMethods.ReceiveSamples_i16(handle, outBuffer, maxSamples); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable Support
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if there aren't any samples available for outputting.
|
/// Releases unmanaged and - optionally - managed resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>nonzero if there aren't any samples available for outputting</returns>
|
/// <param name="alsoManaged"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||||
public int IsEmpty()
|
private void Dispose(bool alsoManaged)
|
||||||
{
|
{
|
||||||
return soundtouch_isEmpty(handle);
|
if (!IsDisposed)
|
||||||
|
{
|
||||||
|
if (alsoManaged)
|
||||||
|
{
|
||||||
|
// NOTE: Placeholder, dispose managed state (managed objects).
|
||||||
|
// At this point, nothing managed to dispose
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeMethods.DestroyInstance(handle);
|
||||||
|
handle = IntPtr.Zero;
|
||||||
|
|
||||||
|
IsDisposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_getVersionId")]
|
#endregion
|
||||||
|
|
||||||
|
#region Native Methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get SoundTouch library version Id
|
/// Provides direct access to mapped DLL methods
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static extern int GetVersionId();
|
private static class NativeMethods
|
||||||
|
{
|
||||||
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_getVersionId")]
|
||||||
|
public static extern int GetVersionId();
|
||||||
|
|
||||||
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_createInstance")]
|
||||||
|
public static extern IntPtr CreateInstance();
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_destroyInstance")]
|
||||||
private static extern IntPtr soundtouch_createInstance();
|
public static extern void DestroyInstance(IntPtr h);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_getVersionString")]
|
||||||
private static extern void soundtouch_destroyInstance(IntPtr h);
|
public static extern IntPtr GetVersionString();
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setRate")]
|
||||||
private static extern IntPtr soundtouch_getVersionString();
|
public static extern void SetRate(IntPtr h, float newRate);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setTempo")]
|
||||||
private static extern void soundtouch_setRate(IntPtr h, float newRate);
|
public static extern void SetTempo(IntPtr h, float newTempo);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setRateChange")]
|
||||||
private static extern void soundtouch_setTempo(IntPtr h, float newTempo);
|
public static extern void SetRateChange(IntPtr h, float newRate);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setTempoChange")]
|
||||||
private static extern void soundtouch_setRateChange(IntPtr h, float newRate);
|
public static extern void SetTempoChange(IntPtr h, float newTempo);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setPitch")]
|
||||||
private static extern void soundtouch_setTempoChange(IntPtr h, float newTempo);
|
public static extern void SetPitch(IntPtr h, float newPitch);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setPitchOctaves")]
|
||||||
private static extern void soundtouch_setPitch(IntPtr h, float newPitch);
|
public static extern void SetPitchOctaves(IntPtr h, float newPitch);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setPitchSemiTones")]
|
||||||
private static extern void soundtouch_setPitchOctaves(IntPtr h, float newPitch);
|
public static extern void SetPitchSemiTones(IntPtr h, float newPitch);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setChannels")]
|
||||||
private static extern void soundtouch_setPitchSemiTones(IntPtr h, float newPitch);
|
public static extern void SetChannels(IntPtr h, uint numChannels);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setSampleRate")]
|
||||||
private static extern void soundtouch_setChannels(IntPtr h, uint numChannels);
|
public static extern void SetSampleRate(IntPtr h, uint srate);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_flush")]
|
||||||
private static extern void soundtouch_setSampleRate(IntPtr h, uint srate);
|
public static extern void Flush(IntPtr h);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_putSamples")]
|
||||||
private static extern void soundtouch_flush(IntPtr h);
|
public static extern void PutSamples(IntPtr h, float[] samples, uint numSamples);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_putSamples_i16")]
|
||||||
private static extern void soundtouch_putSamples(IntPtr h, float[] samples, uint numSamples);
|
public static extern void PutSamples_i16(IntPtr h, short[] samples, uint numSamples);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_clear")]
|
||||||
private static extern void soundtouch_putSamples_i16(IntPtr h, short[] samples, uint numSamples);
|
public static extern void Clear(IntPtr h);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_setSetting")]
|
||||||
private static extern void soundtouch_clear(IntPtr h);
|
public static extern int SetSetting(IntPtr h, int settingId, int value);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_getSetting")]
|
||||||
private static extern int soundtouch_setSetting(IntPtr h, int settingId, int value);
|
public static extern int GetSetting(IntPtr h, int settingId);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_numUnprocessedSamples")]
|
||||||
private static extern int soundtouch_getSetting(IntPtr h, int settingId);
|
public static extern uint NumUnprocessedSamples(IntPtr h);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_receiveSamples")]
|
||||||
private static extern uint soundtouch_numUnprocessedSamples(IntPtr h);
|
public static extern uint ReceiveSamples(IntPtr h, float[] outBuffer, uint maxSamples);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_receiveSamples_i16")]
|
||||||
private static extern uint soundtouch_receiveSamples(IntPtr h, float[] outBuffer, uint maxSamples);
|
public static extern uint ReceiveSamples_i16(IntPtr h, short[] outBuffer, uint maxSamples);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_numSamples")]
|
||||||
private static extern uint soundtouch_receiveSamples_i16(IntPtr h, short[] outBuffer, uint maxSamples);
|
public static extern uint NumSamples(IntPtr h);
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SoundTouchLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "soundtouch_isEmpty")]
|
||||||
private static extern uint soundtouch_numSamples(IntPtr h);
|
public static extern int IsEmpty(IntPtr h);
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("SoundTouch.dll", CallingConvention = CallingConvention.Cdecl)]
|
#endregion
|
||||||
private static extern int soundtouch_isEmpty(IntPtr h);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user