How do I manipulate gain on a wav file? - c#

I have a wav file, and I want to play around with the gain on the sound clip (boost in softer areas, reduce at others. And I need to do this to 1k+ files) and save it back to disk.
.NET doesn't seem to have a sound library, and none of the audio libraries I can find seem to have controls for this (Accord, Naudio, SDL2, SharpDX; though I could just not be seeing what I'm looking for). I've also looked into the WAV format to try and do it directly to the byte stream, but I can't find anything more specific than the data block is left-right pair samples.
So, with access to a .wav file, how can I adjust the loudness on a per sample basis? If possible, I'd also like a solution that would allow me to seamlessly work with other sound file formats as well.

NAudio seems to provide what you are looking for
ISampleProvider
The strength of IWaveProvider is that it can be used to represent
audio in any format. It can be used for 16,24 or 32 bit PCM audio, and
even for compressed audio (MP3, G.711 etc). But if you are performing
any kind of signal processing or analysis on the audio, it is very
likely that you want the audio to be in 32 bit IEEE floating point
format. And it can be a pain to try to read floating point values out
of a byte[] in C#.
So ISampleProvider defines an interface where the samples are all 32
bit floating point
public interface ISampleProvider {
WaveFormat WaveFormat { get; }
int Read(float[] buffer, int offset, int.count);
}
https://github.com/naudio/NAudio/blob/master/Docs/WaveProviders.md#isampleprovider
Create custom SampleProvider that takes an input SampleProvider in your constructor. Use input Sample Provider to get samples, multiply by your gain:
Output sample = gain x input sample
Use WaveFileWriter.CreateWaveFile feeding customSampleProvider.ToWaveProvider() to the appropriate argument, to output back to wav file.

Related

How to convert stored MP3 file data (byte[]) into a float[] Unity can use as AudioSource-Data?

I did tons of research during the last days and nothing helped me out for my special problem. I am writing my own music engine for a Unity3d game and for this I created custom files containing the mp3 data and other information.
What I'm trying to do now is to take these split up mp3-byte-arrays (which can be played when I store them individually, I tested it - so the audio data seems to be fine) and convert them to Unity's AudioSource(s) somehow. I think converting the byte[] into a float[] containing the needed sample data of my audio would be enough, because audioClip.setData( ... ); should do the trick then (I hope).
But I continuously fail at decompressing and/or converting my raw mp3 buffer[] to anything like float[] - and even if I somehow succeed, the only thing I hear is nasty whitenoise-like nonsense.
Any ideas? I would love to hear from you and solve this problem!
Implementation of a decompression algorithm that will take a compressed MP3 stream and output it as uncompressed data is not a trivial task. You can either find a library that does this (I am not aware of any), or work around the issue in some way.
You can use untiy engine to decompress (aka play back) through an AudioSource, and sample it then, or execute some FFMPEG command line to get the wav. Most ways of doing it are cumbersome and ideally you should find a way of not doing it at all.
byte[] or float[] is not really a signifficant difference here - the difference is encoded vs raw

NAudio playing multiple sounds together gives exception "All mixer inputs must have the same WaveFormat"

I am trying to play multiple sound files at the same time using NAudio MixingSampleProvider's AddMixerInput method. I am using the AudioPlaybackEngine found at this page: https://gist.github.com/markheath/8783999
However, when I tried to play different files, I get an exception while playing some sounds: "All mixer inputs must have the same WaveFormat" It is probably because the sound files I have do not have the same sample rate (I see some files have 7046 as sample rate, instead of 44100).
Is there a way to modify the CachedSound class so that the sample rates are all converted to 44100 when reading the files?
Thanks!
You cant mix audio streams together without converting them to the same sample rate. In NAudio there are three ways of accessing a resampler:
WaveFormatConversionStream - this uses the ACM resampler component under the hood. Note that you may have issues resampling IEEE float with this one.
MediaFoundationResampler - this uses MediaFoundation. It allows you to adjust the resampling quality.
WdlResamplingSampleProvider - this is brand new in the latest NAudio, and offers fully managed resampling.
As well as matching sample rates, you also need matching channel counts. NAudio has various ways to turn mono into stereo and vice versa.

Audio pitch analysis

I'm very new to sound analysis in fact doing it for the first time all I need to do is to analyse an mp3 file or any other format and detect as pitch varies. simply I want to trim audio file where high notes occur.
sound wave
I've tried NAudio and few articles but of no avail so if someone guides me in right direction for some tutorial and what API to use.
The first you must know is how the pitch is related to waveform.
Notice: simple single-channel waveform is represented by simple byte array. It consists of RIFF header with some necessary parameters and the wave sequence itself. More complicated waveforms (multichannel, high bit rate) are represented in some other way (int instead of byte array, interference and so on).
SO: In order to manipulate audio pitch, you have to learn how waveform is made (step 2) and write (or google) a certain algorithm, which will operate with a waveform's pitch in a way mentioned in step 1.
If you are very new to audio programming, there is a great beginner tutorial: generating constant waveforms with C#.
You could use an FFT to get the spectrum of the recording. By checking the spectrum for specific frequencies you could decide which parts of the audio contain high pitches.
Some theory:
http://en.wikipedia.org/wiki/Fourier_transform
http://en.wikipedia.org/wiki/Spectrogram
Some resources:
How to perform the FFT to a wave-file using NAudio
https://naudio.codeplex.com/discussions/257586
http://naudio.codeplex.com/discussions/242989
Try a C# binding to Aubio
aubio is a tool designed for the extraction of annotations from audio signals. Its features include segmenting a sound file before each of its attacks, performing pitch detection, tapping the beat and producing midi streams from live audio.
http://aubio.org/

Audio output from Silverlight

I'm looking to develop a Silverlight application which will take a stream of data (not an audio stream as such) from a web server.
The data stream would then be manipulated to give audio of a certain format (G.711 a-Law for example) which would then be converted into PCM so that additional effects can be applied (such as boosting the volume).
I'm OK up to this point. I've got my data, converted the G.711 into PCM but my problem is being able to output this PCM audio to the sound card.
I basing a solution on some C# code intended for a .Net application but in Silverlight there is a problem with trying to take a copy of a delegate (function pointer) which will be the topic of a separate question once I've produced a simple code sample.
So, the question is... How can I output the PCM audio that I have held in a data structure (currently an array) in my Silverlight to the user? (Please don't say write the byte values to a text box)
If it were a MP3 or WMA file I would play it using a MediaElement but I don't want to have to make it into a file as this would put a crimp on applying dynamic effects to the audio.
I've seen a few posts from people saying low level audio support is poor/non-existant in Silverlight so I'm open to any suggestions/ideas people may have.
The simple answer is that there is no support for PCM playback from Silverlight in version 2. So unless you want to write a fully managed PCM to MP3 converter you are stuck. Even then I'm not sure you could get the MediaElement to play from isolated storage.
Is there any chance you could use a web service to perform the conversion?
See also this question:
Where's the sound API in Silverlight? Or, how do I write a music app to run in the browser?
Update: Silverlight 3 supports your custom audio sources. However, it won't let you intercept samples to perform effects on WMA or MP3, presumably for DRM reasons, so you would still potentially need to write your own decoder.
Short answer is use a MediaElement + a MediaStreamSource
Check out these:
http://blogs.msdn.com/gillesk/archive/2009/03/23/playing-back-wave-files-in-silverlight.aspx
http://code.msdn.microsoft.com/wavmss/Release/ProjectReleases.aspx?ReleaseId=2417
Basically, write a decoder in managed code to convert G.711 a-Law to PCM, then do whatever modifications you want to the raw values, then pass those into a MediaStreamSource.
Looks like Silverlight 3 supports direct PCM output now, or will when released. I don't see anything in the docs about the raw AV pipeline yet.
Mark Heath's answer is correct - only certain formats are supported - mp3 and certain flavours of WMA (unfortunately not WMA lossless which would be 'closer' to PCM).
To play PCM data in Silverlight, you could do the following:
* Convert the PCM into mp3 data, and store it in memory.
* Play the mp3 data using the technique presented at ManagedMediaHelpers. The idea here involves a class called Mp3MediaStreamSource (derived from System.Windows.Media.MediaStreamSource) that provides mp3 chunks to a MediaElement to play. The chunks will need to be in a stream, but of course a memory stream will do.
I initially thought you might be able to provide PCM chunks via MediaStreamSource, but this does not work. It's a real shame as it would solve your problem (and the one I was facing - making a Speex audio file player) really easily!

WAV file auto repeat in C#

I have a 10 second sound effect wave file. What I would like to do is take that file and repeat it n number of times and then save the longer WAV file to disk. This way I can create a much longer background effect rather than auto-repeat on the media player which is a bit stuttered between repeats. I am trying to do this in C#.
That's reasonably easy to do, given the WAV file format - assuming it's uncompressed audio (most WAV files are - or at least, they were last time I had anything to do with them).
There may well be audio APIs you can use to do this without getting stuck into the binary format, but I suspect they'd take as long to learn as just doing it yourself as you're not doing anything particularly complicated.
If you only need to do this with a small number of files, you might as well do it by hand with Audacity.
If you're using .Net 2.0 or higher then you can use the System.Media.SoundPlayer class and specifically its PlayLooping method to achieve what you want with no stuttering. This is preferable to creating a new wav file - it means less disk space for the file and less memory needed to render the sound. In general you should always use buffered techniques like this for audio playback if the sound will be looped or is longer than a few seconds.
You can do this easily in C# using the NAudio .NET audio library. You would need to use the WaveFileReader and WaveFileWriter classes. You can also use it to create a custom WaveStream that will loop your audio as many times as you want without the need to create a long WAV file.

Categories