|
|
Comments and Discussions
|
|
 |

|
Hey guys, I have been doing some experimenting with WAV files and I need to be able to play an WAV file from a stream. What I am going to be doing is opening a file, getting the raw data of the wav file. I do this by using this class provided by NightFox:
http://www.codeproject.com/KB/audio-video/CSharpWAVClassAndMixing.aspx
Then when I have the raw data, I extract it using the WAVFile's built in function GetNextSampleAs16Bit().
Here is the class that I have made:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Aurasen
{
class InternalWAVFile
{
private MemoryStream mMemoryStream;
private bool mStereo;
private int mSampleRateHz;
private short mBitsPerSample;
private int mDataSizeBytes;
public InternalWAVFile(short[] samples, bool pStereo, int pSampleRateHz, short pBitsPerSample)
{
if (mMemoryStream != null)
{
mMemoryStream.Close();
mMemoryStream.Dispose();
mMemoryStream = null;
}
mMemoryStream = new MemoryStream();
mStereo = pStereo;
mSampleRateHz = pSampleRateHz;
mBitsPerSample = pBitsPerSample;
Create();
foreach (short s in samples)
{
byte[] buffer = BitConverter.GetBytes(s);
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer);
AddSample_ByteArray(buffer);
}
mMemoryStream.Close();
}
public MemoryStream GetStream()
{
return mMemoryStream;
}
private void AddSample_ByteArray(byte[] pSample)
{
try
{
int numBytes = pSample.GetLength(0);
mMemoryStream.Write(pSample, 0, numBytes);
}
catch
{
}
}
private void Create()
{
try
{
byte mNumChannels = mStereo ? (byte)2 : (byte)1;
char[] mWAVHeader = new char[4];
char[] mRIFFType = new char[4];
"RIFF".CopyTo(0, mWAVHeader, 0, 4);
"WAVE".CopyTo(0, mRIFFType, 0, 4);
byte[] buffer = StrToByteArray("RIFF");
mMemoryStream.Write(buffer, 0, 4); if (mWAVHeader == null)
mWAVHeader = new char[4];
"RIFF".CopyTo(0, mWAVHeader, 0, 4);
Array.Clear(buffer, 0, buffer.GetLength(0));
mMemoryStream.Write(buffer, 0, 4);
buffer = StrToByteArray("WAVE");
mMemoryStream.Write(buffer, 0, 4);
if (mRIFFType == null)
mRIFFType = new char[4];
"WAVE".CopyTo(0, mRIFFType, 0, 4);
buffer = StrToByteArray("fmt ");
mMemoryStream.Write(buffer, 0, 4);
Array.Clear(buffer, 0, buffer.GetLength(0));
buffer[0] = 16;
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer);
mMemoryStream.Write(buffer, 0, 4);
Array.Clear(buffer, 0, buffer.GetLength(0));
buffer[0] = 1;
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer, 0, 2);
mMemoryStream.Write(buffer, 0, 2);
Array.Clear(buffer, 0, buffer.GetLength(0));
buffer[0] = mNumChannels;
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer, 0, 2);
mMemoryStream.Write(buffer, 0, 2);
buffer = BitConverter.GetBytes(mSampleRateHz);
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer);
mMemoryStream.Write(buffer, 0, 4);
short bytesPerSample = 0;
if (mStereo)
bytesPerSample = (short)((mBitsPerSample / 8) * 2);
else
bytesPerSample = (short)(mBitsPerSample / 8);
int mBytesPerSec = mSampleRateHz * bytesPerSample;
buffer = BitConverter.GetBytes(mBytesPerSec);
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer);
mMemoryStream.Write(buffer, 0, 4);
byte[] buffer_2bytes = BitConverter.GetBytes(bytesPerSample);
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer_2bytes);
mMemoryStream.Write(buffer_2bytes, 0, 2);
buffer_2bytes = BitConverter.GetBytes(mBitsPerSample);
if (!BitConverter.IsLittleEndian)
Array.Reverse(buffer_2bytes);
mMemoryStream.Write(buffer_2bytes, 0, 2);
buffer = StrToByteArray("data");
mMemoryStream.Write(buffer, 0, 4);
Array.Clear(buffer, 0, buffer.GetLength(0));
mMemoryStream.Write(buffer, 0, 4);
mDataSizeBytes = 0;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static byte[] StrToByteArray(String pStr)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
return encoding.GetBytes(pStr);
}
}
}
But for some reason when I used this function to play audio like this:
All it does is say the Header information is corrupted, even though I am using the same method of building a wav file content as the creator of the WAVFile class uses.
Does anyone have any suggestions?
class Program
{
static void Main(string[] args)
{
Console.WriteLine("hi");
WAVFile audioFile = new WAVFile();
string warning = audioFile.Open("11.wav", WAVFile.WAVFileMode.READ);
short[] audioSample = new short[audioFile.NumSamples];
if (warning == "")
{
for (int sampleNum = 0; sampleNum < audioFile.NumSamples; ++sampleNum)
{
audioSample[sampleNum] = audioFile.GetNextSampleAs16Bit();
}
}
InternalWAVFile iwf = new InternalWAVFile(audioSample, audioFile.IsStereo, audioFile.SampleRateHz, audioFile.BitsPerSample);
MemoryStream ms = iwf.GetStream();
if (null == ms)
Console.WriteLine("stream is null");
else
{
Console.WriteLine("Not null");
Audio a = new Audio();
Console.WriteLine("Going to play");
a.Play(ms, Microsoft.VisualBasic.AudioPlayMode.Background);
Console.WriteLine("Played");
}
}
}
|
|
|
|

|
Hey guys. I actually figured out the problem. Apparently when NightFox creates the WAV file from the FileStream in his own class, Windows will automatically change the data length value and total file size value when its created. So he puts 0 in these positions. But when playing directly from a stream, and not creating an actual WAV file, it does not fill these values in automatically, so I had to manually put them in. In this case, the data size is simply the length of my short[] array multiplied by 2. And the file size is that number plus 28.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
A C# class for reading and writing WAV files, light audio manipulation, and WAV file mixing.
| Type | Article |
| Licence | CPOL |
| First Posted | 20 Apr 2009 |
| Views | 98,757 |
| Downloads | 5,970 |
| Bookmarked | 67 times |
|
|