Coder Social home page Coder Social logo

Comments (6)

mackron avatar mackron commented on June 2, 2024 1

Thanks for the taking the time to investigate this. The MONO, NONE, NONE channel map was a surprise to me. I'll review your findings ASAP and report back.

from miniaudio.

mackron avatar mackron commented on June 2, 2024

Well mono means 1, so it doesn't make sense to have more than one channel for a mono stream. For example, if a microphone is capturing a monaural stream, why would it ever make sense to report anything more than 1 channel?

What is the specific contents of the channel map? Is it MONO, FRONT_LEFT, FRONT_RIGHT? If so, that makes no sense and will be why that validation is failing.

from miniaudio.

JonathanGirardeau avatar JonathanGirardeau commented on June 2, 2024

Thank you for your answer, I have tried again and it seems the content of channel map is:

MA_CHANNEL_MONO,
MA_CHANNEL_NONE,
MA_CHANNEL_NONE

After diving into miniaudio code my understanding is:
In function ma_device_init__pulse:

cmap = sourceInfo.channel_map;

At this point cmap = [1,2,7,0,0,0,0,...]

/* Use a default channel map. */ ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MA_PA_CHANNEL_MAP_DEFAULT);

After this call: cmap = [0,-1,-1,-1,-1,-1,-1,...]
Then descriptorCapture.channelMap = [1,0,0,0,0,0,0,...].
Then device->capture.internalChannelMap = descriptorCapture->channelMap.
Then converterConfig.pChannelMapIn = pDevice->capture.internalChannelMap.
Then ma_channel_map_is_valid(pConfig->pChannelMapIn, pConfig->channelsIn) returns false.

from miniaudio.

JonathanGirardeau avatar JonathanGirardeau commented on June 2, 2024

I think I have found a problem.
ss.channels value is 3 but it is overwritten to 1:

/* Use the requested channel count if we have one. */
if (pDescriptorCapture->channels != 0) {
    ss.channels = pDescriptorCapture->channels;
}

Then cmap is overwritten with a default channel map with 1 channel (cmap = [0,-1,-1,-1,-1,-1,-1,...]):

/* Use a default channel map. */
((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MA_PA_CHANNEL_MAP_DEFAULT);

Then ss is overwritten by pActualSS, so ss.channels value changes from 1 to 3:

/* Internal format. */
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
if (pActualSS != NULL) {
    ss = *pActualSS;

Then cmap is copied in pDescriptorCapture->channelMap with 3 channels however it maps only 1 channel.

pDescriptorCapture->channels   = ss.channels;
...
if (pDescriptorCapture->channels > 2) {
    for (iChannel = 0; iChannel < pDescriptorCapture->channels; ++iChannel) {
        pDescriptorCapture->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
    }
}

from miniaudio.

mackron avatar mackron commented on June 2, 2024

Sorry for the delay on this one. I've pushed a potential fix for this to the dev branch if you were wanting to try that out. It now queries the channel map after creating the stream and uses that instead of the cmap channel map that's constructed prior to creating the stream.

from miniaudio.

JonathanGirardeau avatar JonathanGirardeau commented on June 2, 2024

Hello, thanks for looking at my issue.
I have tested on the dev branch and it works, however after debugging I have found that the issue has been fixed by this commit #701.
Before this commit, the flag MA_PA_STREAM_FIX_CHANNELS was added (in my case) to streamFlags and that's why ss.channels changes back from 1 to 3:

/* Internal format. */
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pDevice->pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
if (pActualSS != NULL) {
    ss = *pActualSS;

MA_PA_STREAM_FIX_CHANNELS: Use the number of channels and the channel map of the sink, and possibly ignore the number of channels and the map the sample spec and the passed channel map contain.
ref

After the fix, I was a bit surprised by miniaudio logs:

[PulseAudio] Capture attr: maxlength=6144, tlength=2048, prebuf=-1, minreq=-1, fragsize=2048; periodSizeInFrames=512
[PulseAudio] Capture sample spec: format=32-bit Signed Integer, channels=1, rate=16000
[PulseAudio] Capture actual attr: maxlength=8192, tlength=2048, prebuf=-1, minreq=-1, fragsize=2048; periodSizeInFrames=512
[PulseAudio]
  Scarlett 4i4 USB Analog Surround 2.1 (Capture)
    Format:      32-bit Signed Integer -> 16-bit Signed Integer
    Channels:    1 -> 1
    Sample Rate: 16000 -> 16000
    Buffer Size: 512*4 (2048)
    Conversion:
      Pre Format Conversion:  NO
      Post Format Conversion: YES
      Channel Routing:        NO
      Resampling:             NO
      Passthrough:            NO
      Channel Map In:         {CHANNEL_MONO}
      Channel Map Out:        {CHANNEL_MONO}

Channels: 1 -> 1 surprised me at first but I think it is pulseaudio that does the 3->1 channel mapping and not miniaudio so miniaudio does a simple 1->1 mapping.

from miniaudio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.