diff --git a/README.html b/README.html index 9a5afb2..29fbbb8 100644 --- a/README.html +++ b/README.html @@ -686,18 +686,20 @@ and command-line switch "-bpm"

6. Acknowledgements

-

Kudos for these people who have submitted bugfixed since +

Kudos for these people who have contributed to development or submitted +bugfixes since SoundTouch v1.3.1:

-

Moral greetings to all other contributors as well!

+

Moral greetings to all other contributors and users also!


7. LICENSE

SoundTouch audio processing library
diff --git a/source/SoundTouchDLL/SoundTouchDLL.pas b/source/SoundTouchDLL/SoundTouchDLL.pas new file mode 100644 index 0000000..8b02894 --- /dev/null +++ b/source/SoundTouchDLL/SoundTouchDLL.pas @@ -0,0 +1,469 @@ +unit SoundTouchDLL; + +////////////////////////////////////////////////////////////////////////////// +// +// SoundTouch.dll wrapper for accessing SoundTouch routines from Delphi/Pascal +// +// Module Author : Christian Budde +// +//////////////////////////////////////////////////////////////////////////////// +// +// $Id$ +// +//////////////////////////////////////////////////////////////////////////////// +// +// License : +// +// SoundTouch audio processing library +// Copyright (c) Olli Parviainen +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +//////////////////////////////////////////////////////////////////////////////// + +interface + +uses + Windows; + +type + TSoundTouchHandle = THandle; + + // Create a new instance of SoundTouch processor. + TSoundTouchCreateInstance = function : TSoundTouchHandle; stdcall; + + // Destroys a SoundTouch processor instance. + TSoundTouchDestroyInstance = procedure (Handle: TSoundTouchHandle); stdcall; + + // Get SoundTouch library version string + TSoundTouchGetVersionString = function : PChar; stdcall; + + // Get SoundTouch library version Id + TSoundTouchGetVersionId = function : Cardinal; stdcall; + + // Sets new rate control value. Normal rate = 1.0, smaller values + // represent slower rate, larger faster rates. + TSoundTouchSetRate = procedure (Handle: TSoundTouchHandle; newRate: Single); stdcall; + + // Sets new tempo control value. Normal tempo = 1.0, smaller values + // represent slower tempo, larger faster tempo. + TSoundTouchSetTempo = procedure (Handle: TSoundTouchHandle; newTempo: Single); stdcall; + + // Sets new rate control value as a difference in percents compared + // to the original rate (-50 .. +100 %); + TSoundTouchSetRateChange = procedure (Handle: TSoundTouchHandle; newRate: Single); stdcall; + + // Sets new tempo control value as a difference in percents compared + // to the original tempo (-50 .. +100 %); + TSoundTouchSetTempoChange = procedure (Handle: TSoundTouchHandle; newTempo: Single); stdcall; + + // Sets new pitch control value. Original pitch = 1.0, smaller values + // represent lower pitches, larger values higher pitch. + TSoundTouchSetPitch = procedure (Handle: TSoundTouchHandle; newPitch: Single); stdcall; + + // Sets pitch change in octaves compared to the original pitch + // (-1.00 .. +1.00); + TSoundTouchSetPitchOctaves = procedure (Handle: TSoundTouchHandle; newPitch: Single); stdcall; + + // Sets pitch change in semi-tones compared to the original pitch + // (-12 .. +12); + TSoundTouchSetPitchSemiTones = procedure (Handle: TSoundTouchHandle; newPitch: Single); stdcall; + + + // Sets the number of channels, 1 = mono, 2 = stereo + TSoundTouchSetChannels = procedure (Handle: TSoundTouchHandle; numChannels: Cardinal); stdcall; + + // Sets sample rate. + TSoundTouchSetSampleRate = procedure (Handle: TSoundTouchHandle; SampleRate: Cardinal); stdcall; + + // 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 + // in the middle of a sound stream. + TSoundTouchFlush = procedure (Handle: TSoundTouchHandle); stdcall; + + // Adds 'numSamples' pcs of samples from the 'samples' memory position into + // the input of the object. Notice that sample rate _has_to_ be set before + // calling this function, otherwise throws a runtime_error exception. + TSoundTouchPutSamples = procedure (Handle: TSoundTouchHandle; + const Samples: PSingle; //< Pointer to sample buffer. + NumSamples: Cardinal //< Number of samples in buffer. Notice + //< that in case of stereo-sound a single sample + //< contains data for both channels. + ); stdcall; + + // Clears all the samples in the object's output and internal processing + // buffers. + TSoundTouchClear = procedure (Handle: TSoundTouchHandle); stdcall; + + // Changes a setting controlling the processing system behaviour. See the + // 'SETTING_...' defines for available setting ID's. + // + // \return 'TRUE' if the setting was succesfully changed + TSoundTouchSetSetting = function (Handle: TSoundTouchHandle; + SettingId: Integer; //< Setting ID number. see SETTING_... defines. + Value: Integer //< New setting value. + ): Boolean; stdcall; + + // Reads a setting controlling the processing system behaviour. See the + // 'SETTING_...' defines for available setting ID's. + // + // \return the setting value. + TSoundTouchGetSetting = function (Handle: TSoundTouchHandle; + settingId: Integer //< Setting ID number, see SETTING_... defines. + ): Integer; stdcall; + + + // Returns number of samples currently unprocessed. + TSoundTouchNumUnprocessedSamples = function (Handle: TSoundTouchHandle): Cardinal; stdcall; + + // Adjusts book-keeping so that given number of samples are removed from beginning of the + // sample buffer without copying them anywhere. + // + // Used to reduce the number of samples in the buffer when accessing the sample buffer directly + // with 'ptrBegin' function. + TSoundTouchReceiveSamples = function (Handle: TSoundTouchHandle; + outBuffer: PSingle; //< Buffer where to copy output samples. + maxSamples: Integer //< How many samples to receive at max. + ): Cardinal; stdcall; + + // Returns number of samples currently available. + TSoundTouchNumSamples = function (Handle: TSoundTouchHandle): Cardinal; stdcall; + + // Returns nonzero if there aren't any samples available for outputting. + TSoundTouchIsEmpty = function (Handle: TSoundTouchHandle): Integer; stdcall; + +var + SoundTouchCreateInstance : TSoundTouchCreateInstance; + SoundTouchDestroyInstance : TSoundTouchDestroyInstance; + SoundTouchGetVersionString : TSoundTouchGetVersionString; + SoundTouchGetVersionId : TSoundTouchGetVersionId; + SoundTouchSetRate : TSoundTouchSetRate; + SoundTouchSetTempo : TSoundTouchSetTempo; + SoundTouchSetRateChange : TSoundTouchSetRateChange; + SoundTouchSetTempoChange : TSoundTouchSetTempoChange; + SoundTouchSetPitch : TSoundTouchSetPitch; + SoundTouchSetPitchOctaves : TSoundTouchSetPitchOctaves; + SoundTouchSetPitchSemiTones : TSoundTouchSetPitchSemiTones; + SoundTouchSetChannels : TSoundTouchSetChannels; + SoundTouchSetSampleRate : TSoundTouchSetSampleRate; + SoundTouchFlush : TSoundTouchFlush; + SoundTouchPutSamples : TSoundTouchPutSamples; + SoundTouchClear : TSoundTouchClear; + SoundTouchSetSetting : TSoundTouchSetSetting; + SoundTouchGetSetting : TSoundTouchGetSetting; + SoundTouchNumUnprocessedSamples : TSoundTouchNumUnprocessedSamples; + SoundTouchReceiveSamples : TSoundTouchReceiveSamples; + SoundTouchNumSamples : TSoundTouchNumSamples; + SoundTouchIsEmpty : TSoundTouchIsEmpty; + +type + TSoundTouch = class + private + FHandle : TSoundTouchHandle; + FRate : Single; + FPitch : Single; + FTempo : Single; + FSampleRate : Single; + FChannels : Cardinal; + function GetNumSamples: Cardinal; + function GetNumUnprocessedSamples: Cardinal; + function GetIsEmpty: Integer; + function GetPitchChange: Single; + function GetRateChange: Single; + function GetTempoChange: Single; + procedure SetRate(const Value: Single); + procedure SetPitch(const Value: Single); + procedure SetTempo(const Value: Single); + procedure SetPitchChange(const Value: Single); + procedure SetRateChange(const Value: Single); + procedure SetTempoChange(const Value: Single); + procedure SetChannels(const Value: Cardinal); + procedure SetSampleRate(const Value: Single); + protected + procedure SamplerateChanged; virtual; + procedure ChannelsChanged; virtual; + procedure PitchChanged; virtual; + procedure TempoChanged; virtual; + procedure RateChanged; virtual; + public + class function GetVersionString: string; + class function GetVersionId: Cardinal; + constructor Create; virtual; + destructor Destroy; override; + procedure Flush; virtual; + procedure Clear; virtual; + + procedure PutSamples(const Samples: PSingle; const NumSamples: Cardinal); + function ReceiveSamples(const outBuffer: PSingle; const maxSamples: Integer): Cardinal; + + function SetSetting(const SettingId: Integer; const Value: Integer): Boolean; + function GetSetting(const settingId: Integer): Integer; + + property VersionString: string read GetVersionString; + property VersionID: Cardinal read GetVersionId; + property Channels: Cardinal read FChannels write SetChannels; + property Rate: Single read FRate write SetRate; + property RateChange: Single read GetRateChange write SetRateChange; + property Tempo: Single read FTempo write SetTempo; + property TempoChange: Single read GetTempoChange write SetTempoChange; + property Pitch: Single read FPitch write SetPitch; + property PitchChange: Single read GetPitchChange write SetPitchChange; + property SampleRate: Single read FSampleRate write SetSampleRate; + + property NumSamples: Cardinal read GetNumSamples; + property NumUnprocessedSamples: Cardinal read GetNumUnprocessedSamples; + property IsEmpty: Integer read GetIsEmpty; + end; + +implementation + +uses + SysUtils; + +{ TSoundTouch } + +constructor TSoundTouch.Create; +begin + inherited; + FHandle := SoundTouchCreateInstance; + FRate := 1; + FTempo := 1; + FPitch := 1; + FChannels := 1; + FSampleRate := 44100; + SamplerateChanged; + ChannelsChanged; +end; + +destructor TSoundTouch.Destroy; +begin + SoundTouchDestroyInstance(FHandle); + inherited; +end; + +procedure TSoundTouch.Flush; +begin + SoundTouchFlush(FHandle); +end; + +procedure TSoundTouch.Clear; +begin + SoundTouchClear(FHandle); +end; + +function TSoundTouch.GetIsEmpty: Integer; +begin + result := SoundTouchIsEmpty(FHandle); +end; + +function TSoundTouch.GetNumSamples: Cardinal; +begin + result := SoundTouchNumSamples(FHandle); +end; + +function TSoundTouch.GetNumUnprocessedSamples: Cardinal; +begin + result := SoundTouchNumUnprocessedSamples(FHandle); +end; + +function TSoundTouch.GetPitchChange: Single; +begin + result := 100 * (FPitch - 1.0); +end; + +function TSoundTouch.GetRateChange: Single; +begin + result := 100 * (FRate - 1.0); +end; + +function TSoundTouch.GetTempoChange: Single; +begin + result := 100 * (FTempo - 1.0); +end; + +class function TSoundTouch.GetVersionId: Cardinal; +begin + result := SoundTouchGetVersionId; +end; + +class function TSoundTouch.GetVersionString: string; +begin + result := StrPas(SoundTouchGetVersionString); +end; + +procedure TSoundTouch.SetChannels(const Value: Cardinal); +begin + if FChannels <> Value then + begin + FChannels := Value; + ChannelsChanged; + end; +end; + +procedure TSoundTouch.ChannelsChanged; +begin + assert(FChannels in [1, 2]); + SoundTouchSetChannels(FHandle, FChannels); +end; + +procedure TSoundTouch.SetPitch(const Value: Single); +begin + if FPitch <> Value then + begin + FPitch := Value; + PitchChanged; + end; +end; + +procedure TSoundTouch.PitchChanged; +begin + SoundTouchSetPitch(FHandle, FPitch); +end; + +procedure TSoundTouch.putSamples(const Samples: PSingle; + const NumSamples: Cardinal); +begin + SoundTouchPutSamples(FHandle, Samples, NumSamples); +end; + +procedure TSoundTouch.RateChanged; +begin + SoundTouchSetRate(FHandle, FRate); +end; + +function TSoundTouch.ReceiveSamples(const outBuffer: PSingle; + const maxSamples: Integer): Cardinal; +begin + result := SoundTouchReceiveSamples(FHandle, outBuffer, maxSamples); +end; + +procedure TSoundTouch.SetPitchChange(const Value: Single); +begin + Pitch := 1.0 + 0.01 * Value; +end; + +procedure TSoundTouch.SetRate(const Value: Single); +begin + if FRate <> Value then + begin + FRate := Value; + RateChanged; + end; +end; + +procedure TSoundTouch.SetRateChange(const Value: Single); +begin + Rate := 1.0 + 0.01 * Value; +end; + +procedure TSoundTouch.SetSampleRate(const Value: Single); +begin + if FSampleRate <> Value then + begin + FSampleRate := Value; + SamplerateChanged; + end; +end; + +procedure TSoundTouch.SamplerateChanged; +begin + assert(FSampleRate > 0); + SoundTouchsetSampleRate(FHandle, round(FSampleRate)); +end; + +procedure TSoundTouch.SetTempo(const Value: Single); +begin + if FTempo <> Value then + begin + FTempo := Value; + TempoChanged; + end; +end; + +procedure TSoundTouch.SetTempoChange(const Value: Single); +begin + Tempo := 1.0 + 0.01 * Value; +end; + +function TSoundTouch.GetSetting(const SettingId: Integer): Integer; +begin + result := SoundTouchGetSetting(FHandle, SettingId); +end; + +function TSoundTouch.SetSetting(const SettingId: Integer; + const Value: Integer): Boolean; +begin + result := SoundTouchSetSetting(FHandle, SettingId, Value); +end; + +procedure TSoundTouch.TempoChanged; +begin + SoundTouchsetTempo(FHandle, FTempo); +end; + +var + SoundTouchLibHandle: HINST; + SoundTouchDLL: PAnsiChar = 'SoundTouch.DLL'; + +procedure InitDLL; +begin + SoundTouchLibHandle := LoadLibrary(SoundTouchDLL); + if SoundTouchLibHandle <> 0 then + try + SoundTouchCreateInstance := GetProcAddress(SoundTouchLibHandle, PAnsiChar( 2)); //'soundtouch_createInstance'); + SoundTouchDestroyInstance := GetProcAddress(SoundTouchLibHandle, PAnsiChar( 3)); //'soundtouch_destroyInstance'); + SoundTouchGetVersionString := GetProcAddress(SoundTouchLibHandle, PAnsiChar( 7)); //'soundtouch_getVersionString'); + SoundTouchGetVersionId := GetProcAddress(SoundTouchLibHandle, PAnsiChar( 6)); //'soundtouch_getVersionId'); + SoundTouchSetRate := GetProcAddress(SoundTouchLibHandle, PAnsiChar(17)); //'soundtouch_setRate'); + SoundTouchSetTempo := GetProcAddress(SoundTouchLibHandle, PAnsiChar(21)); //'soundtouch_setTempo'); + SoundTouchSetRateChange := GetProcAddress(SoundTouchLibHandle, PAnsiChar(18)); //'soundtouch_setRateChange'); + SoundTouchSetTempoChange := GetProcAddress(SoundTouchLibHandle, PAnsiChar(22)); //'soundtouch_setTempoChange'); + SoundTouchSetPitch := GetProcAddress(SoundTouchLibHandle, PAnsiChar(14)); //'soundtouch_setPitch'); + SoundTouchSetPitchOctaves := GetProcAddress(SoundTouchLibHandle, PAnsiChar(15)); //'soundtouch_setPitchOctaves'); + SoundTouchSetPitchSemiTones := GetProcAddress(SoundTouchLibHandle, PAnsiChar(16)); //'soundtouch_setPitchSemiTones'); + SoundTouchSetChannels := GetProcAddress(SoundTouchLibHandle, PAnsiChar(13)); //'soundtouch_setChannels'); + SoundTouchSetSampleRate := GetProcAddress(SoundTouchLibHandle, PAnsiChar(19)); //'soundtouch_setSampleRate'); + SoundTouchFlush := GetProcAddress(SoundTouchLibHandle, PAnsiChar(4)); //'soundtouch_flush'); + SoundTouchPutSamples := GetProcAddress(SoundTouchLibHandle, PAnsiChar(11)); //'soundtouch_putSamples'); + SoundTouchClear := GetProcAddress(SoundTouchLibHandle, PAnsiChar(1)); //'soundtouch_clear'); + SoundTouchSetSetting := GetProcAddress(SoundTouchLibHandle, PAnsiChar(20)); //'soundtouch_SetSetting'); + SoundTouchGetSetting := GetProcAddress(SoundTouchLibHandle, PAnsiChar(5)); //'soundtouch_setSetting'); + SoundTouchNumUnprocessedSamples := GetProcAddress(SoundTouchLibHandle, PAnsiChar(10)); //'soundtouch_numUnprocessedSamples'); + SoundTouchReceiveSamples := GetProcAddress(SoundTouchLibHandle, PAnsiChar(12)); //'soundtouch_receiveSamples'); + SoundTouchNumSamples := GetProcAddress(SoundTouchLibHandle, PAnsiChar(9)); //'soundtouch_numSamples'); + SoundTouchIsEmpty := GetProcAddress(SoundTouchLibHandle, PAnsiChar(8)); //'soundtouch_isEmpty'); + + except + FreeLibrary(SoundTouchLibHandle); + SoundTouchLibHandle := 0; + end; +end; + +procedure FreeDLL; +begin + if SoundTouchLibHandle <> 0 then FreeLibrary(SoundTouchLibHandle); +end; + +initialization + InitDLL; + +finalization + FreeDLL; + +end.