Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] VuMeter Onverwachte Delay

Pagina: 1
Acties:
  • 101 views sinds 30-01-2008
  • Reageer

  • martijnve
  • Registratie: December 2004
  • Laatst online: 12:38
Ik ben een vu meter aan het bouwen in C# hiervoor gebruik ik wat van het internet geplukte code om de data van windows te bemachtigen, via Directx.

Ik krijg nu alle data +/- 1 seconde vertraagt binnen, wat het effect grondig verpest.
Ik ben de hele middag bezig geweest met het vinden van andere voorbeelden maar dat was niet zo succesvol. Er zijn veel vumeter classes te vinden voor als je zelf je geluid speelt, maar dat is dus NIET wat ik wil. Ik wil dat hij reageert op al het geluid wat op de pc wordt afgespeelt.

Hier de codie die ik gevonden heb:
Ik heb hem lang zelf bestudeert en vershillende veranderd en weer getest om te kijken of dat het oplost maar niets hielp. Verder vindt ik het ook raar dat er een seconde vertraging kan komen met een buffer van maar een paar bytes.

De GetVuData() methode roep ik 40 keer per seconde aan vanuit een daarvoor aangemaakte thread. Ik heb bevestigt dat dit gebeurt door eea naar de console te schrijven.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class DXVuMeter
{
    
    private CaptureBuffer buffer;
    private CaptureDevicesCollection audioDevices;
    private int selectedAudioDevice;

    private Int16 bitsPerSample = 16;
    private int samplesPerSecond = 44100;
    private Int16 channels = 2;
    private Int16 samples = 8;
    
    private Int16[] smoothValues;
    private int smoothing = 5;

    public DXVuMeter(int bitsPerSample, int samplesPerSecond, int channels)
    {
        this.bitsPerSample = (Int16)bitsPerSample;
        this.samplesPerSecond = samplesPerSecond;
        this.channels = (Int16)channels;

        audioDevices = new CaptureDevicesCollection();
        selectedAudioDevice = 0;
        
        smoothValues = new Int16[channels];
        smoothValues.Initialize();
    }

    public void StartCapture(){
        Capture capture = new Capture(audioDevices[selectedAudioDevice].DriverGuid);
        CaptureBufferDescription description = new CaptureBufferDescription();
        WaveFormat waveForm = new WaveFormat();

        waveForm.BitsPerSample = bitsPerSample;
        waveForm.SamplesPerSecond = samplesPerSecond;
        waveForm.Channels = channels;
        waveForm.BlockAlign = (short)(waveForm.Channels * waveForm.BitsPerSample / 8);
        waveForm.AverageBytesPerSecond = waveForm.BlockAlign * waveForm.SamplesPerSecond;
        waveForm.FormatTag = WaveFormatTag.Pcm;
       
        description.Format = waveForm;
        description.BufferBytes = 9 * waveForm.BlockAlign;

        buffer = new Microsoft.DirectX.DirectSound.CaptureBuffer(description, capture);
        buffer.Start(true);
    }

    public void StopCapture(){
        buffer.Stop();
    }
    
    public Int16[] GetVuData(){
        Int32[] sampleFormatArray = { this.samples, 2, 1 };
        Array samples = buffer.Read(0, typeof(Int16), LockFlag.FromWriteCursor, sampleFormatArray);

        Int16[] values = new Int16[channels];
        
        for (int i = 0; i < channels; i++){
            for (int j = 0; j < this.samples; j++){
                values[i] += (Int16)samples.GetValue(j, i, 0);
            }
            values[i] = (Int16)(Math.Abs(values[i] / this.samples / 30));
            if (values[i] > 100) values[i] = 100;
        }

        return values;
    }
}

Is er hier iemand die bekend is met dit soort acties en die ziet wat er hier mis is?

[ Voor 6% gewijzigd door martijnve op 02-08-2007 12:37 ]

Mini-ITX GamePC: Core i5 3470 | 16GB DDR3 | GTX 970 4GB | Samsung 830 128GB | Dell u2711 (27", IPS,1440p), 2343BW


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 06-10 13:51

pjvandesande

GC.Collect(head);

Ik moet zeggen, in de code die jij gepost hebt zie ik geen vreemde gebeurtenissen. Weet je zeker dat het niet aan de code ligt die de VuData afspeeld?

  • martijnve
  • Registratie: December 2004
  • Laatst online: 12:38
Daar dacht ik ook aan,
Daarom heb ik het ook getest door gewoon alle data die er uit komt direct naar de console te printen. maar daar zit ook een seconde vertraging in.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace VuMeter
{

    public partial class Form1 : Form
    {
        DXVuMeter vuMeter;
        Display display;
        
        Thread DisplayController;

        public Form1(){
            Form1.CheckForIllegalCrossThreadCalls = false;
        
            InitializeComponent();

            vuMeter = new DXVuMeter(16, 44100, 2);
            display = new Display();

            cbxSoundDevices.DataSource = vuMeter.GetAudioDeviceNames();
        }
        
        private void UpdateDisplay(){
            while (true){       
                Int16[] values = vuMeter.GetVuData();
                Console.WriteLine(values[0]);
                Console.WriteLine(values[1]);
                //display.SetColor(0, values[0], values[0], values[0]);
                //display.SetColor(1, values[1], values[1], values[1]);
                pbVuLeft.Value = values[0];
                pbVuRight.Value = values[1];
                Thread.Sleep(25);
            }
        }

        private void cbxSoundDevices_SelectedIndexChanged(object sender, EventArgs e){
            vuMeter.SetSelectedAudioDevice(cbxSoundDevices.SelectedIndex);
        }

        private void chbxEnabled_CheckedChanged(object sender, EventArgs e){
            if (chbxEnabled.Checked){
                vuMeter.StartCapture();
                DisplayController = new Thread(new ThreadStart(UpdateDisplay));
                DisplayController.Priority = ThreadPriority.Highest;
                DisplayController.Start();
            } else {
                DisplayController.Abort();
                vuMeter.StopCapture();
            }
        }
    }
}

Mini-ITX GamePC: Core i5 3470 | 16GB DDR3 | GTX 970 4GB | Samsung 830 128GB | Dell u2711 (27", IPS,1440p), 2343BW


  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 30-11 12:59

LauPro

Prof Mierenneuke®

Even een wild gokje, die capture is buffered op 1 seconde?

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • martijnve
  • Registratie: December 2004
  • Laatst online: 12:38
Voor zover ik het begrijp is de buffer 8 bytes groot?

Mini-ITX GamePC: Core i5 3470 | 16GB DDR3 | GTX 970 4GB | Samsung 830 128GB | Dell u2711 (27", IPS,1440p), 2343BW


  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 30-11 12:59

LauPro

Prof Mierenneuke®

Als je zegmaar stereo mix op neemt dan moet Windows het geluid 'renderen' naar 1 stream, vervolgens moet het ook nog door de DirectX layer heen waar overal weer eigen buffertjes tussen zitten. Dus ik vind het (onder Windows) niet zo gek dat dat 1 seconde duurt. Misschien even ranzig proberen met een loopback kabel naar de line-in?

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


  • martijnve
  • Registratie: December 2004
  • Laatst online: 12:38
hmm,

En er is geen andere manier? zonder buffer misschien. om gewoon direct die waardes te krijgen?
Heb hier lang naar gezocht maar niets kunnen vinden.

Mini-ITX GamePC: Core i5 3470 | 16GB DDR3 | GTX 970 4GB | Samsung 830 128GB | Dell u2711 (27", IPS,1440p), 2343BW


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 12:58
Uit ervaring weet ik dat je met DirectX toch wel moet kunnen tot rond de 20 tot 50 ms latency komen, een stuk lager dus dan die seconde vertraging die jij krijgt.
Een latency van 9 samples zal je zeker met DirectX niet kunnen halen, dus het lijkt erop dat op het moment dat je de buffer laat vullen dat hiervoor nog een andere buffer gebruikt word.

Voor opname vanuit een line-in is het overigens gebruikelijk dat er met callbacks zodat jouw functie met een bepaalde buffer wordt opgeroepen telkens er nieuwe data binnenkomt. Op die manier heb je de minste latency.
Hoe je dit precies moet doen met c# / directx heb ik geen ervaring mee echter, dus daar kan ik je niet concreet mee helpen.

VirtualDJ 2024 - Fast Image Resizer - Instagram


  • martijnve
  • Registratie: December 2004
  • Laatst online: 12:38
Na nog een middag pielen heb ik ontdekt dat het groter maken van de buffer de vertraging vermindert van ruim een seconde naar +/- 100ms.

Verder klopte er natturlijk niets van de berekeningen in de gevonde code maar dat wist ik al :-P

Als ik tevreen ben zal ik het resultaat wel hier posten, want ik heb tientallen topics gevonden over mensen die problemen hadden met het maken van een vu meter, maar vrijwel nergens bleek uit dat het ook daadwerkelijk gelukt was.

Mini-ITX GamePC: Core i5 3470 | 16GB DDR3 | GTX 970 4GB | Samsung 830 128GB | Dell u2711 (27", IPS,1440p), 2343BW


  • Adion
  • Registratie: Januari 2001
  • Laatst online: 12:58
Het eenvoudigste is om gewoon de grootste sample in je buffer te zoeken en die te gebruiken als huidige vu-waarde. Omdat de samples tussen negatief en positief wisselen kan je dan ook best de absolute waarde gebruiken van je samples.
Op die manier weet je ook zeker dat je vu steeds tussen 0 en 32767 als waarde zal hebben.

VirtualDJ 2024 - Fast Image Resizer - Instagram

Pagina: 1