Timing direct et comptoir de l'échantillon
-
14-11-2019 - |
Question
J'utilise DirectSound pour écrire une onde sinusoïdale sur la carte audio. La taille de l'échantillon est 16 bits, un canal. Ma question est: combien d'échantillons faut-il pour élaborer un son de cinq secondes? La fréquence d'échantillonnage est de 44100 échantillons par seconde. Le calcul est simple: 220500 est la réponse. Cela me rend fou, car mon code ne joue qu'environ la moitié de cette fois !! Voici mon code:
using Microsoft.DirectX.DirectSound;
using System;
namespace Audio
{
// The class
public class Oscillator
{
static void Main(string[] args)
{
// Set up wave format
WaveFormat waveFormat = new WaveFormat();
waveFormat.FormatTag = WaveFormatTag.Pcm;
waveFormat.Channels = 1;
waveFormat.BitsPerSample = 16;
waveFormat.SamplesPerSecond = 44100;
waveFormat.BlockAlign = (short)(waveFormat.Channels * waveFormat.BitsPerSample / 8);
waveFormat.AverageBytesPerSecond = waveFormat.BlockAlign * waveFormat.SamplesPerSecond;
// Set up buffer description
BufferDescription bufferDesc = new BufferDescription(waveFormat);
bufferDesc.Control3D = false;
bufferDesc.ControlEffects = false;
bufferDesc.ControlFrequency = true;
bufferDesc.ControlPan = true;
bufferDesc.ControlVolume = true;
bufferDesc.DeferLocation = true;
bufferDesc.GlobalFocus = true;
Device d = new Device();
d.SetCooperativeLevel(new System.Windows.Forms.Control(), CooperativeLevel.Priority);
int samples = 5 * waveFormat.SamplesPerSecond * waveFormat.Channels;
char[] buffer = new char[samples];
// Set buffer length
bufferDesc.BufferBytes = buffer.Length * waveFormat.BlockAlign;
// Set initial amplitude and frequency
double frequency = 500;
double amplitude = short.MaxValue / 3;
double two_pi = 2 * Math.PI;
// Iterate through time
for (int i = 0; i < buffer.Length; i++)
{
// Add to sine
buffer[i] = (char)(amplitude *
Math.Sin(i * two_pi * frequency / waveFormat.SamplesPerSecond));
}
SecondaryBuffer bufferSound = new SecondaryBuffer(bufferDesc, d);
bufferSound.Volume = (int)Volume.Max;
bufferSound.Write(0, buffer, LockFlag.None);
bufferSound.Play(0, BufferPlayFlags.Default);
System.Threading.Thread.Sleep(10000);
}
}
}
Selon mes calculs, cela devrait jouer pendant 5 secondes. Il joue pour la mi-temps. Si je change
int samples = 5 * waveFormat.SamplesPerSecond * waveFormat.Channels;
à
int samples = 5 * waveFormat.SamplesPerSecond * waveFormat.Channels
* waveFormat.BlockAlign;
Alors le son fonctionne bien, mais c'est un hack, non? Je fais sûrement quelque chose de mal, mais je ne peux pas dire quoi.
Merci pour votre temps.
La solution
Vous aurez 2 octets par échantillon pour 16 bits si je ne me trompe pas, donc le nombre d'octets de tampons sera le double du nombre d'échantillons.