Comment lire des fichiers audio à partir d'un flux en temps réel
J'ai un programme qui produit des signaux audio, qui devait être joué simultanément. Pour cela, j'ai jouer à un intervalle de 100 ms de flux audio dans chaque 100 ms période. Mais j'ai signaux indésirables de début et de fin de chaque 100 ms flux audio (en raison de la DC), de sorte que la sortie son n'est pas lisse, même de la valeur du signal est le même. Mon code est joint ci-dessous. S'il vous plaît aider moi ce que je dois faire pour avoir un bon audio en temps réel.
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);
}
}
static short[] samples = new short[4410]; //100 ms
static CSound sound;
static void Main()
{
Form form = new Form();
form.Show();
sound = new CSound();
Random random = new Random();
for (int i = 0; i < samples.Length; i++)
samples[i] = 1000; //constant value
while (true)
{
sound.Play(samples);
System.Threading.Thread.Sleep(100); //100 ms
}
}
}
}
OriginalL'auteur hossein | 2009-08-19
Vous devez vous connecter pour publier un commentaire.
Si vous cherchez un moyen pour lire des fichiers audio par le biais d'un flux de données défini par, avez-vous considéré NAudio http://naudio.codeplex.com/?
Vous pouvez définir un flux de données, soit à partir d'un fichier ou dans un autre endroit (c'est à dire de la mémoire), puis de renseigner le flux avec les données que vous souhaitez lire. Tant que vous êtes en mesure de continuer à fournir des données audio vers le cours d'eau avant de le pointeur de lecture arrive à la fin de la mémoire tampon, vous ne entendre ces artefacts générés audio.
BTW - je suppose que vous savez que la gestion Directe des bibliothèques X pour .Net ne sont plus en cours d'élaboration et efficacement une impasse pour ce genre de développement Audio?
OriginalL'auteur Sebastian Gray
Il y a un certain nombre de choses de mal avec ce code. Je suppose que lorsque vous exécutez ce code, vous entendez des cliquetis ou des claquements toutes les 100 ms. C'est à cause de la Thread.Sleep(100) appeler à l'intérieur de l'while(true) en boucle. Fondamentalement, votre application est en attente de 100 ms (donner ou prendre une petite quantité de temps), puis de l'appel Play(), qui fait un peu de traitement, puis les files d'attente de la matrice pour la lecture. En conséquence, il y a un petit écart de temps entre la lecture de chaque 100 ms tableau, qui est la production de l'clics.
Cependant, si vous venez de commentaire sur le Thread.Sleep(100) en ligne, votre application serait d'aller dans une boucle infinie où il conserve la mise en attente jusqu'à 100 ms tableau après 100 ms tableau jusqu'à ce que vous avez manqué de mémoire. Mais au moins, la lecture n'aurait pas les artefacts toutes les 100 ms.
Si vous avez modifié la ligne de Fil.Sommeil(80), ce serait un peu mieux, dans le sens où il vous prendrait plus de temps à exécuter de mémoire, mais ce serait encore se produire parce que vous auriez encore être dumping tampons dans la lecture audio du système plus rapide que le système ne peut jouer.
Aussi, même si vous vous débarrassez de l'cliquant sur toutes les 100 ms, vous ne parvenez toujours pas à entendre quoi que ce soit qui sort de vos enceintes, parce que votre code est l'établissement de chaque valeur de l'échantillon à 1000. Vous n'entendez plus rien si vous de varier les valeurs de l'échantillon au cours du temps. D'ailleurs, la seule raison pour laquelle vous entendez des clics à tous est parce que cette valeur de l'échantillon est fixée à 1000, et au cours de ces petits intervalles de temps entre les morceaux de la lecture de la valeur revient à 0. Si vous définissez chaque échantillon de la valeur à 0, vous ne serait jamais entendre quoi que ce soit.
Je pourrais vous aider avec cela, mais j'avais besoin d'avoir une meilleure idée de ce que vous essayez de faire, exactement. Êtes-vous essayer de jouer un son continu d'une certaine fréquence?
OriginalL'auteur MusiGenesis
Si par "signaux indésirables" vous entendez un léger bruit de claquement à chaque extrémité, il pourrait être un problème d'enveloppe, qui dans Csound peut être contrôlée par l 'lin' opcode ou quelque chose de similaire. L'idée étant que vous devez à la rampe jusqu'à l'amplitude sur l'extrémité avant, et vers le bas sur l'extrémité arrière légèrement pour éviter le cliquetis sonore des haut-parleurs brusquement cesser leur sortie dans le milieu de la vague, pour ainsi dire. Quelques ms devrait suffire--expérimenter avec elle jusqu'à ce que vous vous débarrasser de la popping sans remarquer la modulation d'amplitude.
Regardez ici: http://www.csounds.com/journal/issue11/csoundEnvelopes.html
Si vous êtes en essayant de produire un sans couture de signal en articulant à l'identique de la forme d'onde de manière séquentielle, à intervalles réguliers, alors vous aurez toujours entendre ce bruit de claquement parce que la fin d'une forme d'onde ne sont pas alignées avec le début de la forme d'onde. Il est très difficile d'obtenir les formes d'onde à ligne de façon précise, et ce n'est pas vraiment une bonne stratégie. Une meilleure stratégie serait d'utiliser une enveloppe (comme décrit ci-dessus) et le chevauchement de la forme d'onde (appelé colombe-tailing), de sorte que la désintégration de l'ancienne articulation se produit simultanément avec la montée de l'articulation de la nouvelle.
Cependant, cette stratégie ne produira pas un pure son, car la présence de deux sensiblement les mêmes formes d'ondes qui se chevauchent de manière asynchrone va s'annuler les uns les autres un peu et provoquer l'amplitude de diminuer à chaque stade de la forme d'onde.
OriginalL'auteur tjb1982