The MASM Forum

General => The Workshop => Windows API => Topic started by: NoCforMe on June 03, 2025, 11:13:30 AM

Title: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 11:13:30 AM
I'm confused and need a bit o'help here.

I want be able to tap into my soundcard's output, meaning the sound that's currently playing through it (using the card's line input).

There are two Wave functions: waveInOpen() and waveOutOpen().

In reading their descriptions I'm not sure either one is what I want:
But I don't want either to record or to play back: I guess what I want is to intercept the playback stream. Is that an input device or an output device?

I guess I just need to be set straight on the proper point of view here.
Title: Re: How do I get access to my soundcard's output?
Post by: zedd on June 03, 2025, 12:22:09 PM
Some hints that might be useful here...
QuoteWindows (WASAPI/DirectSound):
WASAPI (Windows Audio Session API): The modern API for audio in Windows. It offers low-latency and high-fidelity audio capabilities.
DirectSound: An older API, still available but generally superseded by WASAPI.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 12:29:10 PM
So Zedd, have you actually used this interface? or are you just suggesting something you found after an online search?

Looks a bit too abstract (C++-ish) for my taste.
Title: Re: How do I get access to my soundcard's output?
Post by: zedd on June 03, 2025, 12:34:35 PM
Quote from: NoCforMe on June 03, 2025, 12:29:10 PMSo Zedd, have you actually used this interface? or are you just suggesting something you found after an online search?
No, and from a brief online search.

Siekmanski is probably the best source here for how to proceed with what you are after. He has done extensive work with DirectSound iirc.

The only audio work I (and probably most here) have done is to play an MP3 file. That was pretty simple. What you are after sounds like it will be very complicated, and probably involve COM interfaces, etc.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 12:53:12 PM
Quote from: zedd on June 03, 2025, 12:34:35 PM
Quote from: NoCforMe on June 03, 2025, 12:29:10 PMSo Zedd, have you actually used this interface? or are you just suggesting something you found after an online search?
No, and from a brief online search.

Siekmanski is probably the best source here for how to proceed with what you are after. He has done extensive work with DirectSound iirc.

The only audio work I (and probably most here) have done is to play an MP3 file. That was pretty simple. What you are after sounds like it will be very complicated, and probably involve COM interfaces, etc.

OK. Sorry to ding you here, but in the future, would you please kindly not post any suggestions like that unless you actually know what the fuck they do and how to use them?

Not helpful at all. And yes, I also know how to do online searches, believe it or not.
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 03, 2025, 12:54:16 PM
DirectSound used to let you access the primary output buffer, not sure about the new audio interface (xaudio2).
It can be hard to get access to what's playing because the content creators don't want you to have an easy way to, for example, rip an encoded dvd.

Either way I think you're stuck with an interface or three.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 12:55:45 PM
Quote from: zedd on June 03, 2025, 12:34:35 PMWhat you are after sounds like it will be very complicated, and probably involve COM interfaces, etc.

I sincerely hope not.
I'm merely trying to intercept an audio stream originating from my line-in input to analyze it (actually the output of an electronic device). I don't see why I'd have to use COM here for such a simple thing.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 12:57:11 PM
Quote from: sinsi on June 03, 2025, 12:54:16 PMDirectSound used to let you access the primary output buffer, not sure about the new audio interface (xaudio2).
It can be hard to get access to what's playing because the content creators don't want you to have an easy way to, for example, rip an encoded dvd.

Either way I think you're stuck with an interface or three.

Well, people actually implement things like digital oscilloscopes using the sound card, so they must have some way of accessing the card's stream, right?

(Not what I'm doing, but somewhat similar.)
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 03, 2025, 01:20:19 PM
If we knew the data you're trying to input it might magk it easier.
For true digital data an analogue line-in probably won't work whereas a USB connection might.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 01:37:59 PM
Quote from: sinsi on June 03, 2025, 01:20:19 PMIf we knew the data you're trying to input it might magk it easier.
For true digital data an analogue line-in probably won't work whereas a USB connection might.

The data would be a series of clicks. Basically just short pulses (square wave-ish) generated by a metronome circuit which I want to calibrate.

Why wouldn't line in work where USB would? Line in gets digitized through the sound card.
What's the connection between USB and the sound card?
I guess you can plug in an iPod and have it play through the PC, yes? But I have no experience with that and no knowledge of how it works.
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 03, 2025, 02:43:13 PM
Quote from: NoCforMe on June 03, 2025, 01:37:59 PMLine in gets digitized through the sound card.
The problem is that it takes a variable input (analogue) and converts it to digital.
The signal is sampled e.g. 44100 times a second and the value is somehow converted to a level (electrical?).
Now we have a digital number we need a bitrate, usually 8 or 16, but we also need to work out which level is noise or silence. With digital, 0 is silence and 1 is noise. With analog, the ADC might treat anything below an arbitrary number as silence.

If you are using some type of pulse or square wave it may be easier.
If you know your output you have a better idea of levels and limits, they should be in the specs.


Think of how a serial port works, baud versus samples/sec.
Title: Re: How do I get access to my soundcard's output?
Post by: daydreamer on June 03, 2025, 03:37:52 PM
Instead of sending to USB,sending to external monitor You can get sound, despite sound card speaker is wrecked, or thru Bluetooth headset on newer pc
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 03, 2025, 05:23:25 PM
Quote from: sinsi on June 03, 2025, 02:43:13 PM
Quote from: NoCforMe on June 03, 2025, 01:37:59 PMLine in gets digitized through the sound card.
The problem is that it takes a variable input (analogue) and converts it to digital.
The signal is sampled e.g. 44100 times a second and the value is somehow converted to a level (electrical?).
Now we have a digital number we need a bitrate, usually 8 or 16, but we also need to work out which level is noise or silence. With digital, 0 is silence and 1 is noise. With analog, the ADC might treat anything below an arbitrary number as silence.

Well, it's a little less mysterious than that:
The ADC (analog to digital converter) outputs a number corresponding to the level of the input, where the input is scaled to some value; let's say for example the input ranges between -1 volt and 1 volt, representing the minimum and maximum values. (The level needs to be adjusted electrically on the input to the sound card.) 0 volts input always gives an output of 0; 1 volt would be 32,767 (assuming 16-bit data) and -1 volt would be -32,768, and anything in between is, well, in between.

The other settings--bitrate, # of channels and # of bits--are set through the driver (for a typical .WAV file these would be 44.1KHz, 2 channels and 16 bits). So that's not a problem.

The problem is just how do I get access to this data? I know it's possible, I just don't know how.
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 03, 2025, 05:38:52 PM
Well waveInOpen is your only choice, but Windows needs to know which device it is.
Title: Re: How do I get access to my soundcard's output?
Post by: TimoVJL on June 03, 2025, 06:46:05 PM
Something to read
http://www.techmind.org/wave/ (http://www.techmind.org/wave/)
Title: Re: How do I get access to my soundcard's output?
Post by: adeyblue on June 04, 2025, 01:39:36 AM
QuoteSomething to read
http://www.techmind.org/wave/ (http://www.techmind.org/wave/)
Quoteto be continued...

Last modified: 7 September 2006
Ah, a blogger after my own heart.

There's an MSDN example for doing what this does (recording from the default input) with WASAPI (search IAudioClient Capturing a Stream).
It's about the same amount of code once you modify this example to support arbitrary length recording with multiple WAVE buffers.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 04, 2025, 04:36:55 AM
Yeah, pretty good blog post, nice and clear.
So basically what I imagined doing, opening an input device and setting up sufficient buffers. I think I can handle that.

I'm going to go the waveXXXX() route rather than opening a new can o'worms (WASAPI). Should do everything I need it to do.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 05, 2025, 03:07:04 PM
So, some progress:
I've built my metronome circuit and connected it to my computah's line-in input (via a potentiometer to adjust the level), and I was able to do a recording with Sound Forge (an ancient copy from Windoze 2000 that still works):

Metronome pulses.jpg

(Just to give you an idea, each of those pulses--the vertical things sticking up--is about 900 samples wide at a sampling frequency of 44.1kHz.)

And I've pretty much figured out how to get a look at that sound data with Win32 Waveform Audio functions. Not easy but doable: I'll have to do buffer management, but I think I have a handle on how the whole scheme will work.

Will report back when more progress has been made.
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 05, 2025, 05:27:15 PM
How are you using the menetrome's output? Such an output would be easy to generate for any BPM value, and be exact.
Title: Re: How do I get access to my soundcard's output?
Post by: stoo23 on June 05, 2025, 06:21:36 PM
I must admit, I have NOT been seriously following this thread but Audacity has an In-Built Metronome function and is both Free and a great program !!
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 06, 2025, 02:56:43 AM
Quote from: sinsi on June 05, 2025, 05:27:15 PMHow are you using the menetrome's output? Such an output would be easy to generate for any BPM value, and be exact.

I'm building a physical stand-alone metronome and I want to calibrate its BPM values, hence the connection to the sound card.

Formula is BPM = sampling frequency / # of samples * 60.

I've got it pretty much figured out except for some tricky buffer-management cases:
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 06, 2025, 03:00:39 AM
Quote from: stoo23 on June 05, 2025, 06:21:36 PMI must admit, I have NOT been seriously following this thread but Audacity has an In-Built Metronome function and is both Free and a great program !!

Well, for that matter it would be super easy to write a metronome program.
But I don't want to have to use a desktop computer for that simple function. My metronome fits in a small tin and runs on a 9-volt battery.
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 06, 2025, 10:00:15 AM
Quote from: NoCforMe on June 06, 2025, 02:56:43 AMSpeed really does matter here.
Multithreading should speed things up.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 06, 2025, 10:41:01 AM
Quote from: sinsi on June 06, 2025, 10:00:15 AM
Quote from: NoCforMe on June 06, 2025, 02:56:43 AMSpeed really does matter here.
Multithreading should speed things up.

Yes, the buffer-reading code will go into a separate thread, so the UI remains responsive.
Title: Re: How do I get access to my soundcard's output?
Post by: stoo23 on June 06, 2025, 01:51:47 PM
So do you not have access to an Oscilloscope ??
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 06, 2025, 02:09:46 PM
Quote from: stoo23 on June 06, 2025, 01:51:47 PMSo do you not have access to an Oscilloscope ??

Yes, I do; I have an older Tektronix 475.  But that wouldn't be at all accurate; I might be able to get within 20% of the pulse spacing for BPM. Not good enough.

Might be able to get pretty close with a modren DSO, but I don't have one of those.

The sound card method lets me get super close to exact, as I can actually count samples (1/44,100 sec.).
Title: Re: How do I get access to my soundcard's output?
Post by: stoo23 on June 06, 2025, 02:22:19 PM
Hmmm OK, well, you've effectively Lost me, I would have thought even the 475 @ 200mHz would have been adequate.  :dazzled:
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 06, 2025, 02:34:28 PM
Quote from: stoo23 on June 06, 2025, 02:22:19 PMHmmm OK, well, you've effectively Lost me, I would have thought even the 475 @ 200mHz would have been adequate.  :dazzled:

Yes, it has that bandwidth, but what it doesn't have is enough resolution to calibrate BPM from a (verrrry slow) signal.

Keep in mind how far apart metronome clicks are spaced, which is what I need to measure. 200MHz ain't gonna help there.
Title: Re: How do I get access to my soundcard's output?
Post by: TimoVJL on June 06, 2025, 10:22:06 PM
A long time ago tested a two microphones for testing, how window might dampens noices.
With two similar microphones it might be possible, as switching those, an average value might be quite close.
That project was never accepted, as don't offer any easy solution for persons, who want use their relations for labs.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 07, 2025, 05:24:36 AM
Quote from: TimoVJL on June 06, 2025, 10:22:06 PMA long time ago tested a two microphones for testing, how window might dampens noices.
With two similar microphones it might be possible, as switching those, an average value might be quite close.
That project was never accepted, as don't offer any easy solution for persons, who want use their relations for labs.

Sounds like you were attempting noise cancellation, right?

That's tricky, because you really need an accurate inverse phase signal for that to work. Lotsa signal processing, probably better done in hardware.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 07, 2025, 12:16:34 PM
I figured out how to do Wave Audio recording. Nailed it.
I'm planning on writing a tutorial on it; the one that Timo posted here (http://www.techmind.org/wave/) is pretty good, but it has nothing about buffer management, which is important for any kind of practical recording app.

Here are some details:

The crucial functions here are waveInPrepareHeader(), waveInAddBuffer() and waveInUnprepareHeader(). So just what all do those do?

Well, to make things clearer I'm going to temporarily rename those two "prepare" functions:

because that's what these unfortunately-named functions actually do.

The overall idea is this: to do any kind of serious audio processing, you need at least two buffers for audio data. (I made my testbed work with just two.) While one buffer is being recorded into by the Wave device driver, you can access the other buffer, process it, copy it into another buffer to save to a file, etc.

All this is controlled by the 3 functions listed above.

With just 2 buffers, the sequence is this:

To keep track of things I used two WAVEHDR structures, one for each buffer, and two variables, CurrRecHdr and NextRecHdr; Curr always points to the one currently being filled by the driver, and Next is the one warming up in the bullpen. When the current buffer is done and I'm done with its data, I just swap Curr & Next and continue on my merry way.

Make sense? Yes, it's fairly "low level", which I suppose is why the whole API is now deprecated. But it's not hard to program at all.

Of course, you need to make sure you're done processing the one buffer before the next one fills up, or else some of your recorded data will be lost.

BTW, although I showed how to do this using polling (twiddling your thumbs while waiting for a flag to be set), you can also use callbacks so you don't have to keep checking that flag. The callback can either be to a regular window procedure, or to a special proc only used by this API. However, the latter is pretty useless, because that proc can only call a very limited set of functions, otherwise the whole thing will deadlock. (Apparently it does work with certain Windows versions.) So best to just avoid that method, unless all you're doing is setting some flags or other global variables.

And it's best to put all this into a separate thread for better performance.
Title: Re: How do I get access to my soundcard's output?
Post by: NoCforMe on June 22, 2025, 04:48:19 AM
I wrote up a tutorial on how to do recording with Windows Waveform Audio, attached here.
Wish I had a website to publish this on, but this'll have to do. I think it pretty much covers the subject. Could even be used by non-assembly-language programmers.

(This was inspired by the tutorial that Timo posted a link to earlier in this thread.)
Title: Re: How do I get access to my soundcard's output?
Post by: FORTRANS on June 23, 2025, 09:31:52 PM
Hi,

   I read through your tutorial, briefly.  Seems well written
and explains things reasonably.

Regards,

Steve N.
Title: Re: How do I get access to my soundcard's output?
Post by: sinsi on June 24, 2025, 08:50:24 PM
Nice and easy to follow. Good job :thumbsup: