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.