Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Soundcard Oscilloscope for Pulseview via SDL2 #185

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Harvie
Copy link
Contributor

@Harvie Harvie commented Jun 14, 2022

Hello,
inspired by xoscope http://xoscope.sourceforge.net/
i've created libsigrok driver which enables oscilloscope-like acquisition via arbitrary soundcard.
My goal is to be able to decode 9600 baud UART signal captured by soundcard in pulseview.
I've tested it only on linux, but it uses SDL2 library and therefore should be quite portable (most likely without any modifications, can someone please try to build on windows? there is even sdl2 on android, but i am not sure how that works).

I think the concept is relatively usefull. Definitely for education, but i beleive it can be even useful for serious work, since high-end soundcards now have lots of channels and samplerates in hundreds of kHz. Also on raspberry pi and similar devices you can use rather interresting I2S ADCs with specs far behind your traditional audio needs (even with DC coupling possibilities). Some people even managed to modify cheap usb soundcards to remove DC blocking capacitors enabling them to do DC measurements.

i think in future it might be possible to add continuous acquisition, downsampling for long-term measurements and even triggers (should be quite easy) and more. Anyway here is screenshot of noise captured by my laptop's microphone:

image

image

It can already detect multiple soundcards and lets you chose from them, autodetect number of channels, audio format and sampling rate. (though i might still need to properly scale the signal to some reasonable voltage values)

**

PS.: not sure why i see @uwehermann commits in this PR, my code is in single commit.
(i've based my work on libsigrok 0.5.2, since that is what i use on archlinux and i didn't wanted to use git build of pulseview, perhaps there were some extra commits under that tag)

@Harvie Harvie force-pushed the master branch 4 times, most recently from bb86467 to a80cda7 Compare June 14, 2022 21:01
@Harvie Harvie changed the title Soundcard Oscilloscope for Pulseview via SDL2 [HELP NEEDED] Soundcard Oscilloscope for Pulseview via SDL2 Jun 14, 2022
@Harvie
Copy link
Contributor Author

Harvie commented Jun 14, 2022

I've fixed some issues. Now the only problem i've noticed is that i cannot stop running acquisition by "stop" button in pulseview and have to wait untill all packets are acquired... Any ideas how to fix this?

@Harvie
Copy link
Contributor Author

Harvie commented Jun 14, 2022

Ok, so i fixed that as well. stop button now works. I think it is ready for review.

@acassis
Copy link

acassis commented Jun 23, 2022

Hi @Harvie kudos!!! Really impressive! What sound card did you suggest? It should be nice to find some low cost USB sound-card compatible. :-) Do you think it is possible to get rid of SDL2? It should be nice if it could work directly with pulseaudio instead of depending an external library.

@acassis
Copy link

acassis commented Jun 23, 2022

@Harvie please rebase your branch repository with master to avoid those issue on your PR.

@Harvie
Copy link
Contributor Author

Harvie commented Jun 23, 2022

do you think it is possible to get rid of SDL2? It should be nice if it could work directly with pulseaudio instead of depending an external library.

I don't think it is a good idea to get rid of SDL2. Libsigrok can be used on other platforms than linux (even on linux not everyone is using pulseaudio). SDL2 makes sure it works on different platforms and in futureproof way, so when somebody invents new audio subsystem for linux we will just build with new sdl2 version without having to port libsigrok to it. for example while i was using sigrok, linux world started transition from pulseaudio to pipewire. so it really makes sense to have another layer.

So sdl2 choice was not random, i truly beleive it's a good one. In other words: there's a method to my madnes 🙂

@Harvie
Copy link
Contributor Author

Harvie commented Jun 23, 2022

@Harvie please rebase your branch repository with master to avoid those issue on your PR.

I can do that. Will it work? I don't know if hardware driver api is the same for master...

@acassis
Copy link

acassis commented Jun 24, 2022

@Harvie please rebase your branch repository with master to avoid those issue on your PR.

I can do that. Will it work? I don't know if hardware driver api is the same for master...

Something is out of sync, doing a rebase it you fix those issues. Other option is you start from scratch: git pull the master branch of your repo; create a new branch from master; apply your modifications; create a commit and submit a PR. But doing git rebase will save a lot of time.

@Harvie
Copy link
Contributor Author

Harvie commented Jun 24, 2022

Ok, i've rebased the commit.

@Harvie
Copy link
Contributor Author

Harvie commented Jun 24, 2022

What sound card did you suggest?

Really depends what are you looking for. I use zoom h1n, it is portable recorder which also works as USB soundcard (even on linux), but is not cheap and there are probably better options for that price if you just need soundcard.

If you need something really cheap, there are these $1 soundcards. output seems reasonable (depending on chipset, they all look the same, but some are not good), but input is mono:

image

However 24b soundcards with 192kHz sampling are relatively common nowadays for some reasonable price. Not sure if some of them have 5.1 input. That might help as well.

It might be cool to use the soundcard with some kind ADUM based USB isolator to enable for galvanicaly isolated measurements.

@Harvie
Copy link
Contributor Author

Harvie commented Jun 26, 2022

I beleive that including this code into sigrok will significantly lower entry barrier to experimenting with analog related features of sigrok and therefore will allow more people to play with it without the hassle of acquiring supported scope and hopefully even draw more attention of contributors to challenges of analog signal processing in sigrok.

@acassis
Copy link

acassis commented Jun 28, 2022

I beleive that including this code into sigrok will significantly lower entry barrier to experimenting with analog related features of sigrok and therefore will allow more people to play with it without the hassle of acquiring supported scope and hopefully even draw more attention of contributors to challenges of analog signal processing in sigrok.

Yes, for sure, although there are those very low cost "saleae" clone (in fact they are not clones) that cost less than U$10. But I think this is a nice feature to have on sigrok. Also it could be used as an analog data logger, correct?

@Harvie
Copy link
Contributor Author

Harvie commented Jul 11, 2022

Yes, for sure, although there are those very low cost "saleae" clone

Yes, these are nice. But they cannot capture analog signals. At least the one i have at hand cannot do that. So there's little to none motivation for contributors to develop any analog related features if they only have these saleae analyzers. But virtualy everyone has soundcard, so now the newbies (like me) can explore early support of analog signals, which is already in pulseview.

@nsauzede
Copy link

nsauzede commented Aug 1, 2022

I second the fact that this addition is really helpful, to start playing with Sigrok without any specific hardware, as eg: most Linux systems are sporting a builtin soundcard and SDL2 is available
Please merge this, if possible 👍

@Harvie
Copy link
Contributor Author

Harvie commented Mar 21, 2023

Any news on this one?

@Harvie Harvie requested a review from acassis March 21, 2023 16:19
@acassis
Copy link

acassis commented Apr 6, 2023

Hi @Harvie I don't have write commit permission, so I'm not able to merge it. I don't know what happened with this project, why it is so slow. Let's wait a little bit more! Maybe if more user like @nsauzede comment here it could raise their attention!

@pilatomic
Copy link

Hi Harvie,
I just went through the process of getting a PR merged, so I can help you a bit.
In your PR current state, it still rebases cleanly on the master, which it a good thing, but I think it would be rejected.
Here the things to look after :

  • Ensure each array initialization values are in the "trailing comma" format.
  • Get rid of dead code
  • Replace "printf" by the proper logging facilities of the project

Things I'm not so sure about:

  • I couldnt test it with sigrok-cli, as it does not support multiple devices. Maybe add a way to select a device ? (Seek advice on IRC / mailing list about that one, I'm quite new to the project, so it's possible i'm missing something).

@Harvie
Copy link
Contributor Author

Harvie commented May 13, 2023

In your PR current state, it still rebases cleanly on the master, which it a good thing, but I think it would be rejected.

Recently someone mentioned on mailing list, that github mirror was not updated in a year...
So cannot be really sure about that :-(

https://www.mail-archive.com/[email protected]/msg04444.html

@pilatomic
Copy link

Indeed the GitHub master branch is outdated, but it still rebases cleanly on the master branch of the official repo (git://sigrok.org/libsigrok)
;-)

@Harvie
Copy link
Contributor Author

Harvie commented May 13, 2023

Maybe add a way to select a device ?

In case you have multiple soundcard, you can select which one to use. At least in pulseview it did worked for me.
If sigrok-cli does not support that API, i don't think i am responsible for that. However SDL1 library accepted environment variables specifiing audio device to be used by default, perhaps SDL2 has some similar feature...

@Harvie
Copy link
Contributor Author

Harvie commented May 13, 2023

Ensure each array initialization values are in the "trailing comma" format.
Get rid of dead code
Replace "printf" by the proper logging facilities of the project

I've fixed these issues and pushed updated version to this PR

@Harvie
Copy link
Contributor Author

Harvie commented May 13, 2023

Plugin still leaves some things to be desired. For example support for triggers, which is totaly doable and i would like to add such advanced features. But right now i don't feel like there's much interrest since noone considered merging this in a last year, so such effort would seem rather vain to me...

@christianeisendle
Copy link

christianeisendle commented May 15, 2023

Hi @Harvie ,

first, nice work and actually brilliant idea to come up with a lean driver which supports analog capturing using soundcards - without any HW dependencies on the actual card.

Libsigrok can be used on other platforms than linux (even on linux not everyone is using pulseaudio).

This became actually a huge issue when i was tesing your pull request. I'm not using pulseaudio since it is an audio middleware layer coupled to desktops like Gnome (or in fact it relies on DBUS from what i know) - and i'm more the console user who wants to avoid additional overhead on my Linux boxes.
Anyway, i thought it is easy going by just using ALSA since SDL also has a dedicated ALSA abstraction. It wasn't easy at all.
The problem is that the SDL_GetAudioDeviceSpec() API (which you use to scan for devices) always returned 0 for all dev_spec members. This is not only the case for ALSA but also for some other backends.

The reason can be found here:
https://github.com/libsdl-org/SDL/blob/237348c772b4ff0e758ace83f471dbf8570535e2/src/audio/alsa/SDL_alsa_audio.c#L759

Which means: In case of ALSA the device specs are unknown unless you open the device. The result is that ALSA via SDL2 is not working in pulseview or sigrok-cli because SDL_GetAudioDeviceSpec return e.g. 0 channels.

I made it working by calling SDL_OpenAudioDevice (with all desired SDL_AudioSpec structure set to 0) and obtained SDL_AudioSpec then holds the default settings. Right after that i called SDL_CloseAudioDevice() again.
This works fine for me at least with ALSA.
You can test with ALSA as well by defining SDL_AUDIODRIVER=alsa (see also https://wiki.libsdl.org/SDL2/FAQUsingSDL) and then run pulseview or sigrok-cli.

So just relying on SDL2 is unfortunately not sufficient, we need more testing with different backends - at least the most obvious ones.

@anlif
Copy link

anlif commented Jul 17, 2023

I can try to get this running on macOS 12.1 and Ubuntu Server 22.04. Really cool project.

@anlif
Copy link

anlif commented Aug 24, 2023

another platform to test would be browser via web-assembly, which in principle has access to audio input

@Harvie
Copy link
Contributor Author

Harvie commented Aug 24, 2023

is there web-assembly build of sigrok? there is some sdl2 for webassembly i guess, but not sure sigrok would work anyway...

@anlif
Copy link

anlif commented Aug 25, 2023

No idea, just got the idea while reading about sdl in webassembly for another project

@Harvie
Copy link
Contributor Author

Harvie commented Aug 27, 2023

@christianeisendle That seems as a problem... I am thinking about following fix:

I can create wrapper around SDL_GetAudioDeviceSpec() that will try to call original SDL_GetAudioDeviceSpec() and if that fails, it will try to acquire the specs by opening (and closing) the device before returning failed status. Otherwise the api will be same.

Do you think this will work?

@Harvie
Copy link
Contributor Author

Harvie commented Feb 6, 2024

Also using ALSA directly is not that common anymore. At least not in mainstream distros and there are reasons for that. I am not saying pipewire is perfect, but it's basicaly what everyone does use now instead of ALSA.

@Harvie
Copy link
Contributor Author

Harvie commented Feb 6, 2024

I think i've managed to fix ALSA compatibility by using following wrapper:

int SDL_GetAudioDeviceSpec_open(int index, int iscapture, SDL_AudioSpec *spec)
{
	//ALSA does not allow to fully read specs of device without opening it.
	//This wrapper tries to open device when SDL_GetAudioDeviceSpec() reports device to have 0 channels.
	//See https://github.com/libsdl-org/SDL/blob/237348c772b4ff0e758ace83f471dbf8570535e2/src/audio/alsa/SDL_alsa_audio.c#L759

	int ret = SDL_GetAudioDeviceSpec(index, iscapture, spec);
	if(!ret && spec->channels == 0) {
		sr_err("Failed SDL_GetAudioDeviceSpec(), trying to open device to get specs.");
		SDL_AudioDeviceID d;
		d = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(index, iscapture), iscapture, spec, spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
		if(d) SDL_CloseAudioDevice(d);
	}
	return ret;
}

v3-0001-Preliminary-support-to-use-soundcard-as-oscillosc.patch.txt

@Harvie
Copy link
Contributor Author

Harvie commented Feb 9, 2024

Comments from IRC (mostly by < abraxa_>):

  • not sure why you're not using an int for "SDL_AudioDeviceID dev_count = SDL_GetNumAudioDevices(0);" since
  • may also make sense to use SR_UNIT_PERCENTAGE or SR_UNIT_UNITLESS instead of SR_UNIT_VOLT since we don't actually know the voltage, from what I understand. Don't remember off hand how PV handles non-volt units but that's a separate issue
  • make the driver scanning more verbose
    • The number of devices reported by SDL should be shown at least, so that users learn whether it's the fault of SDL or the driver that nothing shows up (both SDL_GetNumAudioDevices(0); and SDL_GetNumAudioDevices(1);)
    • Log output of SDL_GetCurrentAudioDriver()
  • and also using the code formatting libsigrok follows:

@Harvie Harvie force-pushed the master branch 5 times, most recently from 6a0cfb6 to f96542a Compare February 26, 2024 15:45
@Harvie
Copy link
Contributor Author

Harvie commented Feb 26, 2024

v4-0001-soundcard-as-oscilloscope.patch.txt

PATCH v4 has modifications based on IRC discussion with abraxa_
Most notably:

  • Fixed datatype for result of SDL_GetNumAudioDevices()
  • Using SR_UNIT_UNITLESS instead of SR_UNIT_VOLT
  • Audio subsystem initialization and scanning is more verbose,
    giving out useful details for debuging purposes
  • Better error handling
  • Code was formated to comply with sigrok rules

PATCH v5:
  - fixed freeze when using pulse protocol with pipewire
  - fixed JACK compatibility (forcing integer samples for now)

PATCH v4 has modifications based on IRC discussion with abraxa_
Most notably:
  - Fixed datatype for result of SDL_GetNumAudioDevices()
  - Using SR_UNIT_UNITLESS instead of SR_UNIT_VOLT
  - Audio subsystem initialization and scanning is more verbose,
    giving out useful details for debuging purposes
  - Better error handling
  - Code was formated to comply with sigrok rules

Signed-off-by: Tomas Mudrunka <[email protected]>
@Harvie
Copy link
Contributor Author

Harvie commented Feb 28, 2024

v5-0001-Support-use-of-soundcard-as-oscilloscope-via-SDL2.patch.txt

PATCH v5:

@mindcrime
Copy link

This looks incredibly useful. Really hoping to see this merged into mainline sigrok. Great work, @Harvie!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants