Skip to content

Commit 30946c2

Browse files
committed
created some mono to stereo conversion documentation
1 parent 96f7915 commit 30946c2

File tree

5 files changed

+102
-21
lines changed

5 files changed

+102
-21
lines changed

Docs/ConvertBetweenStereoAndMono.md

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Convert Between Stereo and Mono
2+
3+
NAudio includes a number of utility classes that can help you to convert between mono and stereo audio. You can use these whether you are playing audio live, or whether you are simply converting from one file format to another.
4+
5+
# Mono to Stereo
6+
7+
If you have a mono input file, and want to convert to stereo, the `MonoToStereoSampleProvider` allows you to do this. It takes a `SampleProvider` as input, and has two floating point `LeftVolume` and `RightVolume` properties, which default to `1.0f`. This means that the mono input will be copied at 100% volume into both left and right channels.
8+
9+
If you wanted to route it just to the left channel, you could set `LeftVolume` to `1.0f` and `RightVolume` to `0.0f`. And if you wanted it more to the right than the left you might set `LeftVolume` to `0.25f` and `RightVolume` to `1.0f`.
10+
11+
```c#
12+
using(var inputReader = new AudioFileReader(monoFilePath))
13+
{
14+
// convert our mono ISampleProvider to stereo
15+
var stereo = new MonoToStereoSampleProvider(inputReader);
16+
stereo.LeftVolume = 0.0f; // silence in left channel
17+
stereo.RightVolume = 1.0f; // full volume in right channel
18+
19+
// can either use this for playback:
20+
myOutputDevice.Init(stereo);
21+
myOutputDevice.Play();
22+
// ...
23+
24+
// ... OR ... could write the stereo audio out to a WAV file
25+
WaveFileWriter.CreateWaveFile16(outputFilePath, stereo);
26+
}
27+
```
28+
29+
There's also a `MonoToStereoProvider16` that works with 16 bit PCM `IWaveProvider` inputs and outputs 16 bit PCM. It works very similarly to `MonoToStereoSampleProvider` otherwise.
30+
31+
# Stereo to Mono
32+
33+
If you have a stereo input file and want to collapse to mono, then the `StereoToMonoSampleProvider` is what you want. It takes a stereo `ISampleProvider` as input, and also has a `LeftVolume` and `RightVolume` property, although the defaults are `0.5f` for each. This means the left sample will be multiplied by `0.5f` and the right by `0.5f` and the two are then summed together.
34+
35+
If you want to just keep the left channel and throw away the right, you'd set `LeftVolume` to 1.0f and `RightVolume` to 0.0f. You could even sort out an out of phase issue by setting `LeftVolume` to `0.5f` and `RightVolume` to -0.5f.
36+
37+
Usage is almost exactly the same. Note that some output devices won't let you play a mono file directly, so this would be more common if you were creating a mono output file, or if the mono audio was going to be passed on as a mixer input to `MixingSampleProvider`.
38+
39+
```c#
40+
using(var inputReader = new AudioFileReader(stereoFilePath))
41+
{
42+
// convert our stereo ISampleProvider to mono
43+
var mono = new StereoToMonoSampleProvider(inputReader);
44+
stereo.LeftVolume = 0.0f; // discard the left channel
45+
stereo.RightVolume = 1.0f; // keep the right channel
46+
47+
// can either use this for playback:
48+
myOutputDevice.Init(mono);
49+
myOutputDevice.Play();
50+
// ...
51+
52+
// ... OR ... could write the mono audio out to a WAV file
53+
WaveFileWriter.CreateWaveFile16(outputFilePath, mono);
54+
}
55+
```
56+
57+
There is also a `StereoToMonoProvider16` that works with 16 bit PCM stereo `IWaveProvider` inputs and emits 16 bit PCM.
58+
59+
# Panning Mono to Stereo
60+
61+
Finally, NAudio offers a `PanningSampleProvider` which allows you to use customisable panning laws to govern how a mono input signal is placed into a stereo output signal.
62+
63+
It has a `Pan` property which can be configured between `-1.0f` (fully left) and `1.0f` (fully right), with `0.0f` being central.
64+
65+
The `PanningStrategy` can be overridden. By default is uses the `SinPanStrategy`. There is also `SquareRootPanStrategy`, `LinearPanStrategy` and `StereoBalanceStrategy`, each one operating slightly differently with regards to how loud central panning is, and how the sound tapers off as it is panned to each side. You can experiment to discover which one fits your needs the best.
66+
67+
Usage is very similar to the `MonoToStereoSampleProvider`
68+
69+
```c#
70+
using(var inputReader = new AudioFileReader(monoFilePath))
71+
{
72+
// convert our mono ISampleProvider to stereo
73+
var panner = new PanningSampleProvider(inputReader);
74+
// override the default pan strategy
75+
panner.PanStrategy = new SquareRootPanStrategy();
76+
panner.Pan = -0.5f; // pan 50% left
77+
78+
// can either use this for playback:
79+
myOutputDevice.Init(panner);
80+
myOutputDevice.Play();
81+
// ...
82+
83+
// ... OR ... could write the stereo audio out to a WAV file
84+
WaveFileWriter.CreateWaveFile16(outputFilePath, panner);
85+
}
86+
```

NAudio.sln

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27004.2006
4+
VisualStudioVersion = 15.0.27004.2005
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NAudio", "NAudio\NAudio.csproj", "{DA4F02E3-0B5E-42CD-B8D9-5583FA51D66E}"
77
EndProject
@@ -32,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{778D
3232
EndProject
3333
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{BA7F6DBB-9FC4-49E6-92E4-621EFE4BBBBC}"
3434
ProjectSection(SolutionItems) = preProject
35+
Docs\ConvertBetweenStereoAndMono.md = Docs\ConvertBetweenStereoAndMono.md
3536
Docs\ConvertMp3ToWav.md = Docs\ConvertMp3ToWav.md
3637
Docs\EnumerateOutputDevices.md = Docs\EnumerateOutputDevices.md
3738
Docs\MixTwoAudioFilesToWav.md = Docs\MixTwoAudioFilesToWav.md

NAudio/Wave/SampleProviders/MonoToStereoSampleProvider.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public MonoToStereoSampleProvider(ISampleProvider source)
3030
/// <summary>
3131
/// WaveFormat of this provider
3232
/// </summary>
33-
public WaveFormat WaveFormat { get; private set; }
33+
public WaveFormat WaveFormat { get; }
3434

3535
/// <summary>
3636
/// Reads samples from this provider

NAudio/Wave/WaveProviders/MonoToStereoProvider16.cs

+12-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
42
using NAudio.Utils;
53

64
namespace NAudio.Wave
@@ -10,8 +8,7 @@ namespace NAudio.Wave
108
/// </summary>
119
public class MonoToStereoProvider16 : IWaveProvider
1210
{
13-
private IWaveProvider sourceProvider;
14-
private WaveFormat outputFormat;
11+
private readonly IWaveProvider sourceProvider;
1512
private byte[] sourceBuffer;
1613

1714
/// <summary>
@@ -33,7 +30,7 @@ public MonoToStereoProvider16(IWaveProvider sourceProvider)
3330
throw new ArgumentException("Source must be 16 bit");
3431
}
3532
this.sourceProvider = sourceProvider;
36-
this.outputFormat = new WaveFormat(sourceProvider.WaveFormat.SampleRate, 2);
33+
WaveFormat = new WaveFormat(sourceProvider.WaveFormat.SampleRate, 2);
3734
RightVolume = 1.0f;
3835
LeftVolume = 1.0f;
3936
}
@@ -51,32 +48,28 @@ public MonoToStereoProvider16(IWaveProvider sourceProvider)
5148
/// <summary>
5249
/// Output Wave Format
5350
/// </summary>
54-
public WaveFormat WaveFormat
55-
{
56-
get { return this.outputFormat; }
57-
}
51+
public WaveFormat WaveFormat { get; }
5852

5953
/// <summary>
6054
/// Reads bytes from this WaveProvider
6155
/// </summary>
6256
public int Read(byte[] buffer, int offset, int count)
63-
{
64-
int sourceBytesRequired = count / 2;
65-
this.sourceBuffer = BufferHelpers.Ensure(this.sourceBuffer, sourceBytesRequired);
66-
WaveBuffer sourceWaveBuffer = new WaveBuffer(sourceBuffer);
67-
WaveBuffer destWaveBuffer = new WaveBuffer(buffer);
57+
{
58+
var sourceBytesRequired = count / 2;
59+
sourceBuffer = BufferHelpers.Ensure(this.sourceBuffer, sourceBytesRequired);
60+
var sourceWaveBuffer = new WaveBuffer(sourceBuffer);
61+
var destWaveBuffer = new WaveBuffer(buffer);
6862

69-
int sourceBytesRead = sourceProvider.Read(sourceBuffer, 0, sourceBytesRequired);
70-
int samplesRead = sourceBytesRead / 2;
71-
int destOffset = offset / 2;
72-
for (int sample = 0; sample < samplesRead; sample++)
63+
var sourceBytesRead = sourceProvider.Read(sourceBuffer, 0, sourceBytesRequired);
64+
var samplesRead = sourceBytesRead / 2;
65+
var destOffset = offset / 2;
66+
for (var sample = 0; sample < samplesRead; sample++)
7367
{
7468
short sampleVal = sourceWaveBuffer.ShortBuffer[sample];
7569
destWaveBuffer.ShortBuffer[destOffset++] = (short)(LeftVolume * sampleVal);
7670
destWaveBuffer.ShortBuffer[destOffset++] = (short)(RightVolume * sampleVal);
7771
}
7872
return samplesRead * 4;
7973
}
80-
8174
}
8275
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ NAudio comes with several demo applications which are the quickest way to see ho
6565
- [Choose an audio output device type](Docs/OutputDeviceTypes.md)
6666
- [Enumerate and select Output Devices](Docs/EnumerateOutputDevices.md)
6767
- [Convert an MP3 to WAV](Docs/ConvertMp3ToWav.md)
68+
- [Convert between mono and stereo](Docs/ConvertBetweenStereoAndMono.md)
6869
- [Understand how to convert between any audio formats you have codecs for](http://www.codeproject.com/Articles/501521/How-to-convert-between-most-audio-formats-in-NET)
6970
- [Encode to MP3 or other formats using MediaFoundationEncoder](http://markheath.net/post/naudio-mediafoundationencoder)
7071
- [Implement "Fire and Forget" Playback (e.g. game sound effects)](http://mark-dot-net.blogspot.co.uk/2014/02/fire-and-forget-audio-playback-with.html)

0 commit comments

Comments
 (0)