المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : Problem with play real-time audio signals



C# Programming
08-20-2009, 11:31 PM
I need to develop a program that plays the signals which are arrived from an external device as follow. My problem is that there are artifacts in the onset and offset of each stream (sound.Play(data)).
what's the solution?

using System;
using System.Windows.Forms;
using Microsoft.DirectX.DirectSound;
using System.IO;

namespace TestSound
{
class CSound : Form
{
const int HEADER_SIZE = 44;
const bool FLAG_STEREO = true;
const short BITS_PER_SAMPLE = 16;
const int SAMPLE_RATE = 44100;

int numberOfSamples;
MemoryStream stream;
BinaryWriter writer;
Device ApplicationDevice = null;
SecondaryBuffer buffer = null;
BufferDescription description;

public CSound()
{
try
{
ApplicationDevice = new Device();
}
catch
{
MessageBox.Show("Unable to create sound device.");
ApplicationDevice = null;
return;
}
ApplicationDevice.SetCooperativeLevel(this, CooperativeLevel.Priority);
description = new BufferDescription();
description.ControlEffects = false;
stream = new MemoryStream();
writer = new BinaryWriter(stream);
}

private void AddHeader()
{
stream.Position = 0;

writer.Write(0x46464952); // "RIFF" in ASCII
writer.Write((int)(HEADER_SIZE + (numberOfSamples * BITS_PER_SAMPLE * (FLAG_STEREO ? 2 : 1) / 8)) - 8);
writer.Write(0x45564157); // "WAVE" in ASCII
writer.Write(0x20746d66); // "fmt " in ASCII
writer.Write(16);
writer.Write((short)1);
writer.Write((short)(FLAG_STEREO ? 2 : 1));
writer.Write(SAMPLE_RATE);
writer.Write(SAMPLE_RATE * (FLAG_STEREO ? 2 : 1) * BITS_PER_SAMPLE / 8);
writer.Write((short)((FLAG_STEREO ? 2 : 1) * BITS_PER_SAMPLE / 8));
writer.Write(BITS_PER_SAMPLE);
writer.Write(0x61746164); // "data" in ASCII
writer.Write((int)(numberOfSamples * BITS_PER_SAMPLE * (FLAG_STEREO ? 2 : 1) / 8));
}

public void Play(short[] samples)
{
if (ApplicationDevice == null)
return;

stream.Position = HEADER_SIZE;
numberOfSamples = samples.Length;
for (int i = 0; i < numberOfSamples; i++)
{
writer.Write(samples[i]);
if (FLAG_STEREO)
writer.Write(samples[i]);
}
AddHeader();
stream.Position = 0;

try
{
if (buffer != null)
{
buffer.Dispose();
buffer = null;
}
buffer = new SecondaryBuffer(stream, description, ApplicationDevice);
buffer.Play(0, BufferPlayFlags.Default);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
}

public class Test
{
CSound sound = new CSound();

void Run()
{
short[] data;

port.Read(data);
sound.Play(data);
}
}
}

I think I should find a way to add new stream to current stream instead of destroying the current stream and creating new one(buffer.Dispose(); buffer = null; buffer = new...)
what's your suggestions?