Click here to Skip to main content
Click here to Skip to main content
 

PracticeSharp (or Practice#) - A Utility for Practicing your Musical Instrument with Playback

By , 6 Jan 2012
 
This is an old version of the currently published article.

Introduction

I've been playing an electric guitar for the last two years, but only a few months ago I started to learn with a professional teacher. The level of complexity rose incredibly - from just trying to playing some chords, I'm now playing difficult licks which are pretty hard to get right when a new song is learned. My guitar teacher uses an application to slow down the playback - Amazing Slow Downer.

It is commercial and I have no plans to pay money for it (surely it is affordable, but open source is better and I can tweak it to my preferences).

An open source alternative that I found is called BestPractice. This utility works fine on Windows XP. But - it crashes on Windows 7 Pro 64 bit, the playback quality could have been better, the UI could have been better designed (e.g. volume bar has a tiny thumb button) and most importantly, it is missing a key feature - Presets.
I downloaded the source code, but found out that the code was written in Borland C++ builder - not quite the development environment I was looking forward to develop in.

User Interface and Presets are a point that is worth talking about - In order to get my guitar to have amazing sound effects, I purchased the Boss ME-70 (as shown below) a while ago.

Boss ME-70 Effect Box

This piece of hardware is truly amazing, not just because of the great effects and sound quality, but because the UI design is brilliant. There are no menus - everything is just laid out for immediate intuitive usage. The best part (for me) are presets - You can manually change some settings (for example: Amplifier emulation mode, Compressor and Delay), then once you're happy with the sound, you can keep it by simply saving it to a persistent preset. This is great for practice - you come back the next day and that preset is waiting for you. No need to set it all up from scratch.

I really wanted these presets in a playback practice tool - the ability to define a lick with some slow down factor and perhaps some volume, maybe also set a loop that allows repetitive practice on that section. Once that "playback section" was properly defined, I wanted to be able to save to a preset just like I do with my Boss ME-70.

Previously, when I used BestPractice, I had to write down all the settings on paper and then manually 'dial' them in every time I started practice. With Practice#, I wanted to be able to make these settings persistent and also be able to save the same settings as two or more presets each having a different slow down (speed) so the lick can be played for example as 70% when you start, 85% when you feel more confident and finally 100% for regular speed.
So once I had my internal 'Business Requirement', it was time to move on to Design and Implementation.

Architecture

I decided to go with .NET 2.0, C# and Windows Forms because the .NET Framework/C# is easy and fast to develop with (in particular UI), Windows Forms is very powerful and Visual Studio Express is free.

The architecture diagram shows the different layers of Practice#.
Starting from top to bottom:

  1. User Interface - Responsible for user interface logic and also for controlling the Core Audio Logic ("Back-End") layer
  2. Presets - A collection of persistent user defined settings such as Tempo, Pitch, Volume, etc.
  3. Core Audio Logic - Contains all the specific audio processing logic that is needed for Practice# to function. Controls and coordinates the other frameworks and libraries (NAudio, SoundTouch, Vorbis#). Does not handle any User Interface logic.
  4. NAudio - (3rd Party) An audio playback platform that handles all the lower level API needed to play audio on an operating system.
  5. SoundTouchSharp - A managed C# Interop wrapper to SoundTouch.
  6. SoundTouch - (3rd Party) An audio DSP library that allows time stretching (tempo changes) and pitch changes.
  7. Vorbis# - (3rd Party) A library that reads Ogg Vorbis files and returns the compressed samples as uncompressed PCM samples that can be processed by NAudio.
  8. LibFlacSharp - A managed C# Interop wrapper to libFlac
  9. libFlac - (3rd Party) A C library that reads FLAC files and returns the compressed samples as uncompressed PCM samples that can be processed by NAudio.

Design

Practice# Class Diagram - click to enlarge image

Time Stretching

The biggest problem was how to stretch time - how to change the audio speed (or tempo) without changing its pitch.
What exactly does it mean? If you have some audio file (e.g. mp3 or wav) and you just play it faster by sampling every second sample, then it will run twice as fast as the original audio but the pitch (tone of sound) would go up two times higher - sounding like cartoons.
The same problem happens when you slow down an audio file using a 'naïve' brute-force way: The pitch will go down, e.g., the singer that used to be a Alto will become Bass.
That's not good - the sound should have the same pitch, just slower.

A somewhat similar problem is how to change the pitch of the audio without changing its speed. That use-case is not as useful as the prior use-case but can still be used in some cases - for example for matching keys.
Both use cases - Time Stretching and Pitch Changing are similar since they only change one parameter (time or pitch) but without affecting the other playback parameter (pitch or time, respectively).

The theory behind this problem is very interesting, but beyond the scope of this article. For those who wish to learn more about the theory behind Time Stretching and Pitch Changing, please refer to this page on DSPDimension. The topic is described there in detail, quite comprehensive and compares different algorithms with audio examples.

The basic requirements for a Time Stretching library are:

  1. It has to be open source and LGPL.
  2. It has to run on Windows 32/64.
  3. The audio quality must be good.
  4. An adequate API has to be provided and it has to work with .NET properly. Managed code is preferred but not mandatory.
  5. It must have high performance (low CPU usage) and small latency. High latency is OK for batch utilities, but a front end practicing playback utility must have low latency.

SoundTouch

The only candidate library that matched these requirements was SoundTouch.
SoundTouch is a LGPL C++ Library that provides an API for performing Time Stretching and Pitch Changing.
SoundTouch's quality is pretty good as can be heard from these samples. The main challenge with this library was how to use it from a managed .NET application since it is a native C++ DLL.

SoundTouchSharp

In order to achieve this integration between .NET and SoundTouch, a wrapper was written - It is called SoundTouchSharp. Basically SoundTouchSharp is an C# Interop Class that wraps the SoundTouch C++ native DLL and exposes the DLL's functions as C# managed API.
Note: SoundTouchSharp can be used out of the scope of Practice# for applications that need to implement Time Stretching or Pitch Changing. If, for example, an ASP.NET Web Application needs that functionality, it can use SoundTouchSharp together with SoundTouch.

The main API methods are:

/// <summary>
/// Sets new tempo control value. Normal tempo = 1.0, smaller values
/// represent slower tempo, larger faster tempo.
/// </summary>
public void SetTempo(float newTempo)

///  <summary>
/// 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.
/// </summary>
public void PutSamples(float[] pSamples, uint numSamples)

/// </summary>
/// 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.
/// </summary>
public uint ReceiveSamples(float[] pOutBuffer, uint maxSamples)

The method SetTempo() sets the tempo (or speed) of the playback. It should be set before putting samples into the SoundTouch queue.
The method PutSamples() puts samples into SoundTouch queue. To receive these samples back as time stretched (or pitched changed) samples, the method ReceiveSamples() needs to be called.
When the tempo is not 100% (i.e. regular speed), then it is important to understand that the number of received samples are different than the number of sample put in the queue, due to the inherent nature time stretching. Therefore, the client calling ReceiveSamples() needs to take this fact into account - ReceiveSamples needs to be called until the internal buffer in SoundTouch has no more samples to return.
One call of PutSamples() with X samples might require more than one call to ReceiveSamples(), depending on the tempo value set in SetTempo().

Audio Playback Framework

I had some experience with Audio playback on Windows, but that was done in C++ and DirectSound and it was a pain to directly deal with DirectSound, generally speaking.
My target was to write a practice tool that allows practicing without wasting too much time on core technologies as playing sound.

DirectSound is also unmanaged. Luckily, there is a very good managed library for Audio processing and playback - NAudio. NAudio takes care of all of the low level APIs (like DirectSound) and provides a simple interface which is easy to use, but also easy to extend.
With NAudio, I managed to play sound files after a few minutes, but for dynamic time stretched playback, that was not enough. The main requirement from an interactive practicing tool is to be able to change the tempo on-the-fly. Therefore, a special audio processor was needed, one that can handle samples of different tempos.

Based on an idea that appeared on NAudio's discussion site, the AdvancedBufferedWaveProvider class was created. It manages a queue of audio buffers each starting on a different time (CurrentTime). The AdvancedBufferedWaveProvider doesn't hold too many audio buffers in its queue, new audio buffers are dynamically added to the queue all the time, as needed, with a dynamic time stretched parameter.

This technique allows the user to change the pitch on-the-fly and get the sound to change with low latency.

Ogg Vorbis

I really like open source products and open source formats. That is why I felt odd with a LGPL utility that can only play back WAV (Uncompressed and basically a Microsoft format) or MP3 (Compressed but proprietary).
Ogg Vorbis is compressed and free - Why not use it?
Unfortunately, NAudio (as of writing of this article) does not support out-of-the-box playback of Ogg Vorbis files.
I had to come up with some solution - Luckily, there is a LGPL library named Vorbis# (or csvorbis) that does provide Ogg Vorbis playback support for managed code.
Vorbis# is a port of the Jorbis Java library which itself is a port of the original xiph orbis decoder which was written in C.
In order to allow Vorbis# to work with NAudio, an assembly (project) was written: NAudioOggVorbis. NAudioOggVorbis encapsulates the Vorbis# code and also provides an NAudio Ogg Vorbis adapter class, OggVorbisFileReader, which plugs-in into NAudio as it inherits from the NAudio core abstract class: WaveStream. NAudio takes care of the handling audio playback logic and commands OggVorbisFileReader to return back buffers and/or change file positions when needed. OggVorbisFileReader delegates these requests to a Vorbis# class VorbisFile which takes care of decoding the compressed Ogg Vorbis packets into uncompressed PCM packets. VorbisFile is a high level wrapper of the decoding logic that is implemented by the many Vorbis# classes. Using it as a single point of entry keeps the client code in OggVorbisFileReader nice and clean.
The code OggVorbisFileReader that uses VorbisFile to decode the next packet:

/// </summary>
/// Reads decompressed PCM data from our Ogg Vorbis file.
/// </summary>
public override int Read(byte[] sampleBuffer, int offset, int numBytes)
{
    int bytesRead = 0;
    lock (m_repositionLock)
    {
        // Read PCM bytes from the Ogg Vorbis File into the sample buffer
        bytesRead = m_vorbisFile.read(sampleBuffer, numBytes, 
			_BIGENDIANREADMODE, _WORDREADMODE, _SGNEDREADMODE, null);
    }

    return bytesRead;
}

Once PCM packets are returned to NAudio, NAudio plays them as if they came from any other source - i.e., NAudio has no idea that the packets were originally Ogg Vorbis encoded packets, nor should it care about this fact. That approach proved to be quick and easy to implement - Ogg Vorbis are played back (and slowed down) just like WAV and MP3 files. Mission accomplished.

FLAC

Encouraged by the success of adding Ogg Vorbis playback (and later WMA playback, the details of which I left out), I decided to go on and add support for one more file format (decoder) - FLAC. Ogg Vorbis is a great open source audio format but it is lossy. A Free Lossless Audio Codec (AKA FLAC) which is also compressed would be a nice thing to have.

FLAC is starting to emerge as 'THE' format for audiophiles - its usability is really superb (in terms of quality and file size) and it is very fast to decode.

So, after some Googling and research, I stumbled upon a very nice demo (written by Stanimir Stoyanov) that shows how to decode FLAC files in C#. The demo was decoding FLAC by communicating with the official libFlac C API through P/Invoke calls.

I took Stan's code, added some missing APIs needed for decoding (e.g. Meta data, seek absolute) and re-factored it to be a new C# managed integration layer to libFlac API: LibFlacSharp. I've put Decoder and Encoder API together, though Practice# only uses the decoding API.

LibFlacSharp is a class that can be used by any C# client (not just for Practice#).

Its main decoding API is: (The API is documented very well in libFlac web site.)

/// <summary>
/// C# (.NET) Wrapper for the libFlac library (Written in C++)
/// </summary>
public class LibFLACSharp
{
    ...

    public static extern IntPtr FLAC__stream_decoder_new();
    public static extern bool 
	FLAC__stream_decoder_process_until_end_of_metadata(IntPtr context);
    public static extern bool FLAC__stream_decoder_process_single(IntPtr context);
    public static extern bool FLAC__stream_decoder_finish(IntPtr context);

    ...
} 

The second thing I did was to write an NAudio File Reader adapter that was somewhat similar to the Ogg Vorbis, however it was more complex. libFlac returns Frames in some size which is not equal to the NAudio buffer size. libFlac also works with Callbacks which are inherently not as easy as a direct control. The callbacks are synchronous, as libFlac has no threads, but it is still somewhat cumbersome.

I found an elegant solution to these issues - the FLAC Frame is read into an intermediate samples buffer. Then when NAudio needs new samples to play, first there is an attempt pull samples from the intermediate buffer (if there are such samples available there).

After the buffer samples are used (if at all), and if there are still samples to fill the NAudio playback buffer, then a request is made to libFlac (through LibFlacSharp) to get one more FLAC Frame.

This design pattern is really not new, but in context of Practice# it reminds me of playing a bagpipe..so I will call it the Bagpiper Design Pattern Smile | :)

With a real bagpipe, a bagpiper is blowing air into the bag at his will (FLAC frames) but the actual playing (NAudio Playback) is continuous using the air in the bag (Intermediate FLAC Samples Buffer).

UI Design

As mentioned above, I was aiming for a user interface which would be productive and intuitive by being close in spirit to the Boss ME-70.
Some other elements that I liked, like the Loop controls and Now buttons, were inspired by the design of BestPractice utility.
Minimal menus are used (only for Recent Files, About Form) and only three Modal Dialog (Open File, Preset Description dialogs and About Form) - all other operational aspects of the tool are laid directly on the form.
The 4 presets resemble the 4 Boss presets pedals - only one is active at a time.
To write to a preset, the Write button (Floppy Disk Icon) has to be clicked - at this point, the LEDs of all presets light in Red waiting for the user to select which preset to write into. Once a preset is clicked, the preset settings are written to a file.

To cancel the Preset Write Mode, simply click the Write button again, and all Preset LEDS will revert to Green (regular mode).
While in Preset Write Mode, clicking on another preset essentially acts as a 'Copy Preset' function, because the current preset's settings are going to be written also in the selected preset.

Each audio file automatically gets its own preset file - all these preset files are kept in a user folder %LOCALAPPDATA%\PracticeSharp (e.g. on my Win7 laptop, it is: C:\Users\Yuval\AppData\Local\PracticeSharp). This is good for a few reasons - each file gets its preset persistent without requiring menus, and when a file is re-opened, the correct presets are loaded automatically. If a preset needs to be reset to default values, the user has to click and hold the Eraser icon for a second or more and the current preset would blink a few times in with an orange LED, then all the settings will revert to default. Once again: no menus or modal dialogs.

Implementation - Audio Processing

The heart of Practice# is the PracticeSharpLogic class. It contains the Audio processing thread which is implemented by ProcessAudio and does the following things:

  1. Reads chunks of uncompressed samples from the input file
  2. Processes the samples using SoundTouch
  3. Receives process samples from SoundTouch
  4. Plays the processed samples with NAudio
  5. Handles control logic required for dynamically changing values on-the-fly of: Volume, Loop, Cue and Current Play Position.
  6. Processes the samples through an Equalizer DSP effect, to put the equalizer into effect

The first important code to notice is the reading of samples from the input file (shown in the image above as first green rectangle from top). This is achieved with NAudio's WaveChannel class.
Note: There is a nice trick I used for converting a float array to byte array without actually requiring CPU or memory. The class is ByteAndFloatsConverter and it is based on this discussion.

#region Read samples from file

// Change current play position
lock (m_currentPlayTimeLock)
{
	if (m_newPlayTimeRequested)
	{
		m_waveChannel.CurrentTime = m_newPlayTime;

		m_newPlayTimeRequested = false;
	}
}

// *** Read one chunk from input file ***
bytesRead = m_waveChannel.Read(convertInputBuffer.Bytes, 0,
		convertInputBuffer.Bytes.Length);
// **************************************

#endregion

The second important code to notice is putting the read samples into SoundTouch, via SoundTouchSharp, for DSP processing (shown in the image above as the second green rectangle from top). The requested tempo and pitch are set before the call (in SetSoundSharpValues).

#region Put samples in SoundTouch

SetSoundSharpValues();

// ***                    Put samples in SoundTouch                   ***
m_soundTouchSharp.PutSamples(convertInputBuffer.Floats, (uint)floatsRead);
// **********************************************************************

#endregion

Finally, the third and perhaps most important code receives the processed samples back from SoundTouch and then puts them in the queued buffered player where they will be played by NAudio (shown in the image above as the third green rectangle from top).

#region Receive & Play Samples
// Receive samples from SoundTouch
do
{
	// ***                Receive samples back from SoundTouch            ***
	// *** This is where Time Stretching and Pitch Changing is done *********
	samplesProcessed = m_soundTouchSharp.ReceiveSamples
			(convertOutputBuffer.Floats, outBufferSizeFloats);
	// **********************************************************************

	if (samplesProcessed > 0)
	{
		TimeSpan currentBufferTime = m_waveChannel.CurrentTime;

		// ** Play samples that came out of SoundTouch 
		// by adding them to AdvancedBufferedWaveProvider - the buffered player
		m_inputProvider.AddSamples(convertOutputBuffer.Bytes, 0, 
			(int)samplesProcessed * sizeof(float) * 
			format.Channels, currentBufferTime);
		// *********************************************************************

		// Wait for queue to free up - only then add 
		// continue reading from the file
		while (!m_stopWorker && 
			m_inputProvider.GetQueueCount() > BusyQueuedBuffersThreshold)
		{
			Thread.Sleep(10);
		}
		bufferIndex++;
	}
} while (!m_stopWorker && samplesProcessed != 0);
#endregion

Usage Demonstration

Please see YouTube video.

Source Code

Since CodeProject does not have support for Subversion, I decided to keep the Practice# source code in Google Code.
To obtain the latest sources, please check out the latest Practice# sources.
To obtain the latest binary, please download the latest Practice# binary.

LGPLV3

History

2/9/2011 - 1.2.0

  • Improved slow down playback quality by fine tuning the SoundTouch engine. There is a significant improvement in sound quality when playback is slowed down, in particular for singing/speech parts but also for music.
  • Manual settings are now used instead of the default automatic provide by Sound Touch
  • Added TimeStretchProfiles, to support custom tuning of the SoundTouch engine
  • Fixed minor bug with positionLabel handling: Clicking on it was not working in Pause mode
  • Position Reset (Back to start) keyboard changed from Home (used by other TrackBars by default) to F5

1/22/2011 - 1.0.1

  • NOTE: I apologize, but I released a bad 1.0 version, 1.0.1 replaces 1.0.
  • Added Wix/MSI setup, with dotNetInstaller boot strapper
  • 'Initialized' Status -> Renamed to 'Ready'
  • Fix: When application was loaded, the previous file did not show the loop boundaries ("bar"). Only after playing the file, it then showed up.
  • Major bug fix: Stopping the audio was not done correctly and caused threading issues (lockups) and/or crashes (was noticeable in particular on slower machines I've tested)

12/25/2010 - 0.6.0.0 (Beta 6)

  • FLAC Playback Support
  • (Core) Fixed: WMA playback was broken
  • (Core) Equalizer fine tuning: Lo (Bass) more pronounced

12/19/2010 - 0.5.0.0 (Beta 5)

  • Bug fixes (Core) - Application sometimes crashed when a file was loaded, Stop/Terminate playback logic was incorrect
  • Bug fixes (UI) - Cancel Write mode did not work properly, it caused the preset to be re-selected loosing the current settings, Current Up/Down controls did not transition properly (e.g. decrementing the seconds below zero did not affect minutes)
  • Added logging using NLog (log file resides in %LOCALAPPDATA%\PracticeSharp\Practice#.log)
  • Added central exception handlers that log the exceptions and show a proper dialog

12/12/2010 - 0.4.0.0 (Beta 4)

  • Equalizer controls
  • Keyboard shortcuts
  • Fix: SoundTouch DLL now works properly with SoundTouchSharp in Release Mode
  • Fix: Flickers, Tab Order, Tool Tips, cosmetics

11/27/2010 - 0.3.0.0 (Beta 3)

  • Added playback support for WMA
  • Integrated with new version NAudio 64392. NAudio has incorporated WMA support that was developed in Practice# (based on original code from Idael Cardaso)
  • Bug fixes, mainly stability issues with preset saving and when application was shut down
  • All Playback initialization and termination fully moved into the audio processing thread (not done on main UI thread any longer)
  • Improved playback hiccups - Mainly due to synchronous events from PracticeSharpLogic to MainForm. Now PracticeSharpLogic events are asynchronous.
  • Added support for a command line argument - the filename (to allow running Practice# from command line or through a future shell extension)
  • Code clean up

11/20/2010 - 0.2.1.0 (Beta 2.1), Fully functional utility

  • MP3, WAV and Ogg Vorbis playback
  • Speed change - The ability to slow down or speed up music without changing its pitch
  • Pitch change - The ability to change the pitch of music up or down without changing its speed
  • Loops - Start and End Marker with Cue (waiting a few seconds before the loop starts, useful to get hands back into position)
  • Presets

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

About the Author

Yuval Naveh
Chief Technology Officer Exzac Inc.
United States United States
I've been punching code since the age of 9 when I got my first computer - A Sinclair Spectrum with 48Kb of RAM!
That was a great time, when peek and pokes were the way to do stuff.
Along the way I moved on to PC and never left it (EDIT: Since 2010 a false statement - I fell in love with Android).
I wrote in X86 Assembly, Logo Wink | ;) , Basic, C, C++, Pascal, Delphi, Java and in the last 10 years C#.
 
I am also an amature photographer using Nikon D100, and taking pictures mostly of scenary & nature.
Some of my pictures are presented at:
My photo gallery
(Titles are in Hebrew, but pictures have an international language.. Smile | :) )
 
My linked in profile:
http://www.linkedin.com/in/YuvalNaveh

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions


Discussions posted for the Published version of this article. Posting a message here will take you to the publicly available article in order to continue your conversation in public.
 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHave you noticed an echo affect when reducing tempo below 50%memberPavel Brun29-Apr-13 10:13 
Just curious if you have noticed echo affects when reducing the tempo below 50%. I can't seem to be able to tune it so the sound is smooth below 50%. Any suggestions?
 
Paul
Questionsome side-effects with your algorithmmemberPavel Brun8-Mar-13 10:44 
So, if I use your algorithm and apply the audio effects (i.e., bass/treble adjustments, panning, and volume) before pushing the samples through the SoundTouch engine, the adjustments are not immediately available in the stream. Soundtouch introduce latency which is fine, but if you slow down the tempo and then adjust the volume, you don't get the immediate effect and can take up to several seconds for the affects to be noticeable
 
I understand that it may not be a factor in your particular application, but any suggestions on how to make the effects more immediate.
 
Paul
AnswerRe: some side-effects with your algorithmmemberYuval Naveh29-Mar-13 12:18 
Sorry, just noticed that.
 
I designed Practice# for a particular usage. I don't see a problem with the current implementation in the context it was designed for.
If you find this algorithm/solution inadequate to your purposes, then you are free to change it.
 
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionWhen to apply the Soundtouch changesmemberPavel Brun26-Feb-13 9:49 
I am writing some code that is to incorporate Soundtouch with a number of ISampleProviders from Naudio. Your example has helped. I am wondering if you have any input as to how I make use of your code either as another ISampleProvider, and when to actually apply the tempo changes. Right now, I have the following sequence at this point:
 

--> Custom BufferedWaveReader (that creates a PCM 16-bit audio stream from a MuLAW stream)
--> PCM16BitToSampleProvider
--> BaseTrebleProvider
--> PanningStreamProvider
--> SampleToWaveProvider16
 
Please note that the audio stream comes from a remote source and already gets buffered to a degree. We want to implement a range of 0.1 to 2.0 for tempo changes only.
 
thoughts?
 
Paul
AnswerRe: When to apply the Soundtouch changes [modified]memberYuval Naveh26-Feb-13 14:20 
Hi Paul,
You can use SoundTouchSharp (my C# wrapper to SoundTouch) to perform the changes on the audio samples. Perhaps after PanningStremProvider.
You could build a sound provider that (e.g. TimeStretchProvider) that pushes the samples into SoundTouch and then pulls them back stretched.
Be aware that there is some latency/lag introduced by SoundTouch.
 
That been said, NAudio has changed quite a bit since I wrote this article/project. You might to consult about these issues (Sample Providers) with NAudio's builder Mark Heath, on the NAudio project forum: http://naudio.codeplex.com/[^]
 
Good luck,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein


modified 27-Feb-13 11:46am.

AnswerRe: When to apply the Soundtouch changesmemberPavel Brun27-Feb-13 4:52 
When we alter the tempo, does the overall number of bytes (i.e., floats) change between the incoming samples and the outgoing samples?
 
Paul
GeneralRe: When to apply the Soundtouch changesmemberYuval Naveh27-Feb-13 5:37 
When you change the speed (or tempo) from the default 1.0 factor then you would get more or less samples, depending on the new factor (<1.0 or >1.0 respectively). Note that samples could be floats or bytes - this depends on how you compiles and use SoundTouch.
For example: If you had a 1 minute song, and you now play it at 50% (0.5) then the new time stretched song would be 2 minutes, but would maintain the same pitch.
 
Practice#, the application (not SoundTouch the library) knows how to deal with the varying amount of samples. SoundTouch is agnostic to what you do with the time stretched samples - it is an engine that gets samples as input, processes them, and outputs back other samples which may be of any other length.
 
HTH
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralRe: When to apply the Soundtouch changesmemberPavel Brun3-Mar-13 8:14 
so I got it working to a degree when the tempo is set to 1.0. The audio is not quite clean as it sounds like it is reading off a record player that is picking up dust (i.e., sounds scratchy). When I adjust the tempo, the audio becomes inaudible. Not sure would could be going wrong when I alter the audio as I am getting scratchy audio.
 
Paul
QuestionAdd feature to tune song to instrumentmemberMember 111652511-Nov-12 11:40 
Hi, you have done a nice job. I missed just one key feature, namely to tune the songs in tiny intervals to adjust to the real instrument. I just donwloaded the source code and added this feature for myself. Don't know how to contribute this to your project. But since it's rather simple to do, maybe you could just add this feature. Thanks.
Viktor
AnswerRe: Add feature to tune song to instrumentmemberYuval Naveh11-Nov-12 15:35 
Hi Viktor,
Thanks great, I emailed you
Let's take it offline
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionGuitar practicememberPaul Hildebrandt5-Nov-12 10:36 
Another good piece of software for practicing guitar and learning new music is Rocksmith. It has an interface like Guitar Hero but uses a real guitar.
QuestionMy vote of 5memberAnkush Bansal31-Oct-12 0:02 
It was my dream in collage to create a similar app! it feels like Déjà vu!
AnswerRe: My vote of 5memberYuval Naveh31-Oct-12 4:01 
Great, enjoy!
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionFile savememberMember 198805310-Oct-12 16:14 
This is a great utility - it owuld be nice if you could save your loop, or complete song slowed down/pitch changed to disk so that you could then transfer it to an mp3 player/phone which would enable you to keep practicing the piece when you do not have access to a computer
AnswerRe: File savememberYuval Naveh10-Oct-12 16:40 
Thanks, glad you enjoy Practice#.
 
The export feature is on my radar - I will do it for the next major version (1.6)
My problem is time, but winter shall soon arrive with snow and with no motorcycle riding (major fun, major time investment) I will be able to complete this features as well as other projects I'm working on Smile | :)
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralRe: File savememberMember 198805310-Oct-12 18:27 
Thanks Yuval. You've done a great job with this. Congratulations.
GeneralMy vote of 5membermanoj kumar choubey4-Oct-12 18:32 
Nice
Suggestionother open source solutionmemberMember 35930644-Oct-12 8:58 
Great work!
I use audacity to loop and/or slow down pieces of music.
GeneralRe: other open source solutionmemberYuval Naveh4-Oct-12 9:19 
Thanks.
I did so too before writing Practice# - but I found Audacity to be cumbersome and hard to use for practicing music. It is a music editor, not designed as a practice tool.
One example: Try switching settings, like tempo, on the fly (what I call Presets).
 
If you noticed in the beginning I put a lot of emphasis on a minimal, fast, and productive user interface (see Boss-ME70)
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralMy vote of 5memberchihuase17-Jun-12 16:06 
Amazing app, very well done...
GeneralRe: My vote of 5memberYuval Naveh27-Jun-12 17:10 
Thanks!
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralMy vote of 5memberrittjc9-Jun-12 5:20 
Chris really needs to add a 6-star vote to this thing only for when people do something "up-and-over" like this! You shouldn't be able to vote for a 6 but once a year per user. This one would get my "this-year's" vote. Terrific job, Yuval!
GeneralRe: My vote of 5memberYuval Naveh17-Jun-12 7:19 
Thank you.
Your feedback is fuel for my future projects and efforts.
 
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionSave audiomemberashyour17-Mar-12 2:32 
I want to save processed audio in a sound file so that it can be played any where.
Please help me how to do it.
thanks
AnswerRe: Save audiomemberYuval Naveh3-Apr-12 14:44 
To save audio you can look at the NAudio examples.
http://mark-dot-net.blogspot.com/2011/04/how-to-use-wavefilewriter.html[^]
 
I might add this feature in a future version (i.e. Export)
 
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

NewsPractice# 1.5.0 was releasedmemberYuval Naveh10-Mar-12 1:42 
Released: 3/2/2012
 
- Fixed random crash/hang when loading recent files - DirectSound? is not stable in NAudio, moved instead to WaveOut? (XP) or Wasapi (Vista,7)
- Fixed speed and pitch track bar mouse behavior. Values are now rounded up properly and the ticks are 'sticky'
- Added a 'Show technical log' (F12) use-case. It is useful for viewing & sending the log if things don't work properly for some reason
- Fixed issue when loading files after an existing was loaded. There was a short playback of the old song. (SoundTouch? buffers not flushed properly and had some left over samples). Not affecting stability, but annoying.
- New feature! Vocal Suppression (AKA Voice Removal or Karaoke), note: works on Stereo files only
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionRepeat/Loop Musicmemberjrbrz20-Dec-11 6:39 
how do I make a loop using the same music NAudio.dll?
AnswerRe: Repeat/Loop MusicmemberYuval Naveh20-Dec-11 6:48 
As I explained in a previous post to you, for any NAudio related questions please look at the NAudio forum and also documentation.
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionError: AcmStream Dispose was not called, at AcmStream.Finalize()memberjrbrz20-Dec-11 6:27 
I am using the library NAudio.dll but sometimes I got the error:
AcmStream Dispose was not called
 
at AcmStream.Finalize()
 
how can I solve this?
AnswerRe: Error: AcmStream Dispose was not called, at AcmStream.Finalize()memberYuval Naveh20-Dec-11 6:46 
Is the problem you're facing in the context of PracticeSharp or are you using NAudio library directly?
If the latter is true, I did not write NAudio, so you will have to ask in the NAudio forum:
http://naudio.codeplex.com/discussions[^]
 
If it happened in PracticeSharp, then please send me the file that caused the issue and I'll try to debug it, although the problem seems to have originated in NAudio.
 
I plan to upgrade the NAudio library used in Practice# to the latest version, but it will take some time as the newer version has some major interface changes.
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

QuestionNudioFLAC.csproj missingmembermarcopmp18-Aug-11 23:08 
Hi Yuva !
I can't find the naudioFLAC.csproj, since in google source repository at href="http://code.google.com/p/practicesharp/downloads/list
there is demo app, without the project. Can you help me ? Am i doing something wrong ?
Thank you
.... ah, a GREAT app ! I am an Hammond organist (as well as a seasoned programmer..)
Marco
AnswerRe: NudioFLAC.csproj missingmemberYuval Naveh19-Aug-11 0:42 
Hi Marco,
It is there - please look in SVN under NAudioFlac:
http://code.google.com/p/practicesharp/source/browse/#svn%2Ftrunk%2FNAudioFLAC%2FLibrary[^]
 
You need to connect to SVN, and get the sources from the trunk.
HTH
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralA great app!memberthompsons16-Apr-11 13:37 
Yuval,
I can't thank you enough for the time and effort put into this
application. For those of us musically inclined programmers out there
this was a boon! It also enables the guitar player to steal some nice
"licks" from the banjo, violin, steel guitar and piano players.
By the way, You are responsible for me buying the ME-70. A great
machine for the price! Thank you for sharing this.
Got my big five.
 
Best Regards,
Steven Thompson.
GeneralRe: A great app!memberYuval Naveh17-Apr-11 1:59 
Hi Steven,
 
Thanks for the kind compliments! Blush | :O
I'm glad to see that Practice# utility does it purpose.
 
As for Boss ME-70 - Yes, a great effect box.
 
Regarding "musically inclinded..", my teacher Ryan is a pro musician (mainly guitar and bass, in a band that tours) - he too uses slow down software (though not mine, because he would only use mac..He asked if I can convert to Mac..), and the last thing you can say that he is inclined. I know you're just kidding, but the software can and is used by all levels of musicians - entry level to pros. For that reason, I published Practice# on cnet so that more musicians (not just programmers) get exposed to it.
 
Cheers, Cool | :cool:
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralI looks super cool!memberShane Story9-Feb-11 6:17 
Good job! This looks like a really neat article. I also play guitar and like music and program.
Shane
Jesus loves you! John 3:16 · Rom 3:23 · Rom 6:23 · Rom 10:9

GeneralMy vote of 5memberGuido_d9-Feb-11 5:22 
Excellent article, very detailed, practical use, original work. Great job!
GeneralPractice# 1.2.0 was releasedmemberYuval Naveh9-Feb-11 4:18 
* Improved slow down playback quality by fine tuning the SoundTouch? engine. There is a significant improvement in sound quality when playback is slowed down, in particular for singing/speech parts but also for music.
* Manual settings are now used instead of the default automatic provide by Sound Touch.
* Added TimeStretchProfiles?, to support custom tuning of the SoundTouch? engine.
* Fixed minor bug with positionLabel handling: Clicking on it was not working in Pause mode
* Position Reset (Back to start) keyboard changed from Home (used by other TrackBars? by default) to F5
 
The google code site also contains a version that has a WiX/MSI Installer.
 
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

NewsQuick update from the oven.. [modified]memberYuval Naveh25-Jan-11 15:46 
I'm working right now on Time Stretch Profile - this allows me to tune the slow down much better then the automatic/default given by SoundTouch.
 
Also, profiles allow you, the user, to select a custom profile that matches the type of the playback.
Speech for example (per request of one of the users) has its own new profile and when it slows down there is hardly noticeable echoing and reverbs (!) though the voice becomes somewhat robotic at low-very slow speeds.
 
So stay tuned.. the next version will slow better.
 
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralRe: Quick update from the oven..memberNejimon CR26-Jan-11 3:55 
That would be great, waiting for it....
GeneralRe: Quick update from the oven..memberYuval Naveh27-Jan-11 16:10 
Hi,
 
I checked in the sources, but also uploaded an experimental version that supports Time Stretch Profiles:
http://code.google.com/p/practicesharp/downloads/detail?name=Practice%23_1_2_0%20(Experimental).zip
 
There are currently 5 hard coded profiles, 2 of them deal with speech - I think you'll like how it slows down speech.
 
Also, the default has changed from Automatic (indeed too much echoing and reverb) to my manual profile: Rock/Pop 1 which has much better slow down qualities.
 
Please let me know how it works.
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralRe: Quick update from the oven..memberNejimon CR29-Jan-11 6:25 
Oh... Now it's close to perfection.... Thanks
Where can I download the source code? the Zip file contains binaries only.
GeneralRe: Quick update from the oven..memberYuval Naveh29-Jan-11 7:28 
Thanks! I thought you'd like it. Smile | :)
The sources are in GoogleCode Subversion Repository - You need to use a Subversion client (e.g. Tortoise SVN) to check them out.
Note: I'm going to release a version (1.2) next week with all of these changes, after more testing.
So you can use the latest sources, but don't forget to check out the new versions.
 
BTW: As an outcome of this tuning exercise, there is a new manual Time Stretch Profile which was tuned (subjectively by my ears..) to be an optimum of clarity for Rock/Pop music and speech.
So I changed the default Sound Touch slow down settings, not just for your usage, but for general use - it sounds much better for music especially for singing parts.
Thanks for bringing this issue up - it just shows the value of user feedback.
 
Cheers,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralRe: Quick update from the oven..memberYuval Naveh9-Feb-11 4:21 
Please note I've released version 1.2.0 that contains the improved slow down playback quality profiles.
Also note that you can change the Time Stretch Profile manually by clicking ALT + CTRL + P.
A combo box would then show a list of available time stretch profiles (currently all hard coded in the code, but Speech is a profile you might prefer to use).
I hid that feature since I think most users don't really care about this - it is too technical, and also the combo box clutters the user interface.
 
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralMy vote of 5memberRoberto Collina24-Jan-11 11:37 
A 12 from me!
 
...actually a 5, but the app is over the top, really Smile | :)
 
Especially handy for those furious prog metal solos. Thanks again for sharing!
GeneralRe: My vote of 5 [modified]memberYuval Naveh24-Jan-11 11:52 
Thanks, Roberto!
Really appreciate your kind words.
It's fun getting feedback - I worked really hard on this utility, and feedback is like fuel for me.
 
BTW: I'm fine tuning right now the slow down algorithm, and the results sound even better now.
So stay tuned - once I release the next version, you should get even sound quality when you slow down.
 
Cheers, Cool | :cool:
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein
modified on Monday, January 24, 2011 6:04 PM

QuestionAudio skips or reverbs?memberNejimon CR21-Jan-11 18:59 
Hi Yuval,
First of all, It is awesome. I was looking for something like this when I was developing an application which plays a dictation system where audio needs to be slowed down without changing pitch. I downloaded the zip and tried it with a wav file and an mp3 file. There is always an effect like audio is skipping at normal speed, which sounds more like a constant echo or reverb at lower speeds. Because of this, some words are skipped or played only partially. Any way to work around this?
AnswerRe: Audio skips or reverbs? [modified]memberYuval Naveh22-Jan-11 3:29 
Hi,
 
I'd like to assist you with this.
First, can you please describe the system you are using? Hardware/CPU/Memory/OS/Sound car?
Audio skipping could happen in a slow machine, though I tested with slower/old laptops (Lenovo T42, Gateway MT3705) and it worked smoothly.
I exposed a configuration property named Latency in the XML Application config file (PracticeSharp.exe.config). The Latency is measured in msec.
Try increasing that value (say to 250 or more) and please let me know if this helps.
 
Could you send a sample of a sound file that caused issues (send me a url to the file - for example, upload to imgur.com) Perhaps the problem is with the specific encoding of that file.
 
Could you test on another machine and verify that the problem exists? Maybe there is a problem with that particular first machine.
 
Once I have more information, I could try to figure this out and fix it.
 
UPDATE: I'm not sure if it is related, but I released 1.0 which was a bad version. Try 1.0.1. Don't think it is related to problem you described though.
 
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein
modified on Saturday, January 22, 2011 10:11 PM

AnswerRe: Audio skips or reverbs?memberYuval Naveh22-Jan-11 16:29 
It took me some hours to ingest what you wrote - but you want to use the system for dictation, which is speech..
If you have the problems with regular speed, that is speed factor = 1 i.e. no slow down, then it is a technical problem and the rest of my answer is not relevant.
 
HOWEVER - if you have the problems with slowed down playback (speed factor < 1) then it makes sense. A lot of sense.
The utility was not designed for speech. It was designed for playback of music.
If you read the article, you'll notice that Practice# is using SoundTouch library for slowing down playback.
If you read the SoundTouch readme:
SoundTouch
 
then you will find the default configuration (which I have not changed) is targeted for playing Rock/Pop music.

"The time-stretch algorithm has few parameters that can be tuned to optimize sound quality for certain application. The current default parameters have been chosen by iterative if-then analysis (read: "trial and error") to obtain best subjective sound quality in pop/rock music processing, but in applications processing different kind of sound the default parameter set may result into a sub-optimal result."

 
This really explains the echo/reverb effect that you described.
 

The table below summaries how the parameters can be adjusted for different applications:
 
Parameter name Default value magnitude Larger value affects... Smaller value affects... Effect to CPU burden
SEQUENCE_MS
Default value is relatively large, chosen for slowing down music tempo Larger value is usually better for slowing down tempo. Growing the value decelerates the "echoing" artifact when slowing down the tempo. Smaller value might be better for speeding up tempo. Reducing the value accelerates the "echoing" artifact when slowing down the tempo Increasing the parameter value reduces computation burden
SEEKWINDOW_MS
Default value is relatively large, chosen for slowing down music tempo Larger value eases finding a good mixing position, but may cause a "drifting" artifact Smaller reduce possibility to find a good mixing position, but reduce the "drifting" artifact. Increasing the parameter value increases computation burden
OVERLAP_MS
Default value is relatively large, chosen to suit with above parameters. If you reduce the "sequence ms" setting, you might wish to try a smaller value. Increasing the parameter value increases computation burden

 

You have a few options:
1. You can try to use SoundTouch Utility (They have a command line utility which is easy to use) directly and play with the parameters until you get to good results for your application.
2. OR/AND after step 1 - You can re-compile Practice# source code and modify the default initialization settings for SoundTouch (I'll expose them to the application config in the next version - can't harm)
3. OR/AND - You can use SoundTouchSharp from C# and write your own application.
 
Hope that makes sense.
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

GeneralRe: Audio skips or reverbs?memberNejimon CR23-Jan-11 7:40 
Thanks for the reply.
In fact I am using a Core I3 machine with 2 GB RAM running Windows XP Professional. Sound card is on-board Realtek HD Audio.
Even at normal speed, it is not the real dictation that comes out (it is a wave file). I tried a couple of mp3 songs. It was played more naturally. Anyway, I will try to use the SoundStretch utility that comes along with SoundTouch and get back to you.
 
I am not allowed to share the original dictation file, since it is a confidential medical content.
GeneralRe: Audio skips or reverbs?memberYuval Naveh23-Jan-11 8:21 
Did you try using a larger Latency value as I suggested?
This is very important piece of information for me to know.
 
Also please verify that Normal Speed is 1 but clicking on the Speed Label. This should cause SoundTouch to not affect the sound.
I just recorded my self talking and played it in Practice# 1.0.1, on Speed 1 - there are no issues what so ever. It sounds the same in WinAmp and Audacity.
 
When I slowed down playback there are some artifacts:
From 0.8-1.0 - not noticeable.
Below that, at 0.7, starts noticeable reverb and echoing (which is expected).
Below 0.5 the effects are very pronounced.
 
I'm going to expose the SoundTouch parameters to the config file - Once I do, I'll let you know and you can take them from GoogleCode SVN.
 
Thanks,
Yuval
"The true sign of intelligence is not knowledge but imagination." - Albert Einstein

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130617.1 | Last Updated 6 Jan 2012
Article Copyright 2010 by Yuval Naveh
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid