Page MenuHomeFreeBSD

sound examples: Add mmap example
Needs ReviewPublic

Authored by meka_tilda.center on Fri, Nov 14, 12:39 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sat, Dec 6, 12:23 PM
Unknown Object (File)
Thu, Dec 4, 12:25 AM
Unknown Object (File)
Wed, Dec 3, 12:41 AM
Unknown Object (File)
Tue, Dec 2, 4:17 PM
Unknown Object (File)
Mon, Dec 1, 12:05 PM
Unknown Object (File)
Sun, Nov 30, 11:36 PM
Unknown Object (File)
Sun, Nov 30, 11:22 AM
Unknown Object (File)
Thu, Nov 27, 9:32 AM
Subscribers

Details

Summary

This example combines mmap and kqueue, but for some reason sound is bad sometimes, which suggests race condition. If kqueue+mmap combination has some fundamental problem, we should at least document why this approach is a bad idea.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

meka_tilda.center created this revision.
meka_tilda.center set the repository for this revision to rG FreeBSD src repository.

This is an initial quick review, as I haven't had a chance to properly test it yet.

Both configs in main() open /dev/dsp, so there is no need two have two configs and duplicate the logic twice. You can have one config but with mode = O_RDWR | O_EXCL | O_NONBLOCK, and call mmap() with PROT_READ | PROT_WRITE on the same FD. Or am I missing something?

share/examples/sound/mmap.c
40 ↗(On Diff #166400)
42 ↗(On Diff #166400)
47–49 ↗(On Diff #166400)
53 ↗(On Diff #166400)
54–56 ↗(On Diff #166400)

The Makefile needs to be updated to install mmap.c.

I also did some tests and there is a lot of distortion.

share/examples/sound/mmap.c
4–8 ↗(On Diff #166400)

That's the strange thing. If I run it 20-30 times, I would get roughly half of the times distorted sound, half of the times normal sound. Also, I tried having one config and two events for read and write, but I couldn't produce any sound like that. Anyway, let me fix this example to conform to the comments and lets go from there.

Remove extra functions as they are very simple

I forgot to edit Makefile. Fixed now.

That's the strange thing. If I run it 20-30 times, I would get roughly half of the times distorted sound, half of the times normal sound. Also, I tried having one config and two events for read and write, but I couldn't produce any sound like that.

I think this is probably a timing issue. I haven't looked into it yet but my guess it that we are not reading/writing exactly when we should.

share/examples/sound/mmap.c
70 ↗(On Diff #166783)

Since we have a mmap field in struct config, wouldn't it make sense to do that in oss_init()?

Let me try to compensate the drift by reading SNDCTL_DSP_GETIPTR and SNDCTL_DSP_GETOPTR and experiment with that for a bit.

Map or allocate buffer in oss_init. For some reason with this patch probability of producing proper sound is way higher. I still have to add GETIPTR/GETOPTR checks and usleep based on the position.

share/examples/sound/mmap.c
30 ↗(On Diff #166857)

This could go in oss.h, and we could remove it from other examples files as well. Again, best in a separate patch.

share/examples/sound/oss.h
230 ↗(On Diff #166857)

We don't check for NULL here. You can do that in a separate patch though, it's not related to mmap.

meka_tilda.center marked an inline comment as done.

Remove needless include

I think this needs to be rebased since we committed the oss.h changes.

Are you working on the timing issues? I haven't really looked into those.

I am looking into the code in general and I want to figure out how to display information so it makes more sense, not just dump printf.

I think I'll try my luck with http://manuals.opensound.com/developer/mmap_test.c.html first and fit it into our example and once the usleep version works, see what are the values of ptr compared to the ones in kqueue scenario. My thinking is "if I can't fix it, move to simpler example", which I'm hoping the official docs are. Anyway, I didn't give up on this code, I just need to approach it from the different angle, for now.

The usleep based mmap example based on official OSS example. There are three big things about it right now that make it not-so-perfect:

  1. It works for cases where in and out config have matching numbers for buffer (channels, fragments, ...)
  2. Calculating duration for usleep would be more optimal. Asking the kernel to fetch playback pointer every 1ms is a big overhead.
  3. It still has glitches sometimes, but the probability of that happening is way lower than previous examples.

I added -v which will print ci.ptr so it is a bit easier to see where the playback pointer is at. Once the example works, I'll remove this option.

Lowering usleep time and checking if ci.ptr is zero made all the glitches in the sound go away. I do need to run it for quite a few times to validate that, but in the worst case I significantly lowered the probability of gibberish on the output. Next, I need to calculate the usleep time based on ci.ptr.