locked
WASAPI Metro Store App: IEEE Float 32-bit to PCM 16-bit

    Question

  • I'm facing a major issue and I can't seem to find a suitable answer.

    I'm using PJSip on a Windows 8.1 Metro App. Currently, PJSip does not support WASAPI and, therefore, I'm developing a library in order to have sound capabilities in my App.

    I'm giving to IAudioClient::Initialize a format of PCM 16-bits 2 channels. However, after initializing and asking for IAudioClient::GetMixFormat the WAVEFORMATEX returned is something like:

    wFormatTag=65534
    nChannels=2
    nSamplesPerSec=44100
    nAvgBytesPerSec=352800
    nBlockAlign=8
    wBitsPerSample=32
    cbSize=22

    So, as far as I can understand I have to "resample" everytime I call IAudioRender::GetBuffer(). Right?

    I've tried several things but I can't accomplish to to the resampling.

    hr = strm->default_pb_dev->GetCurrentPadding(&padding);
    frame_to_render = strm->pb_max_frame_count - padding;
    hr = strm->pb_client->GetBuffer(frame_to_render, &cur_pb_buf);
    

    So, "frame_to_render" seems to be the number of frames I'm requesting to WASAPI.

    And then I have this:

    ws->pb_format->nAvgBytesPerSec=64000:
    strm->bytes_per_frame = ws->pb_format->nAvgBytesPerSec * 20 / 1000

    (...) pj_uint16_t* destBuffer = (pj_uint16_t*)malloc(frame_to_render * strm->bytes_per_frame * sizeof(pj_uint16_t)); pj_uint32_t* sample32 = (pj_uint32_t*)cur_pb_buf; int destOffset = 0; for (int sample = 0; sample < strm->bytes_per_frame; sample++) { destBuffer[sample] = (pj_uint16_t)(sample32 [sample] / 65536); }

    The main problem is that it seems that cur_pb_buf[x] is always '0'. However, when sending that buffer to PJSip I have sound but with cuts.

    Can someone help me in here?

    Monday, March 24, 2014 9:33 AM

All replies

  • I'll have our media expert check out this post.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Monday, March 24, 2014 7:17 PM
    Moderator
  • For playback, you could also use XAUDIO2 which would do the sample rate conversion for you...
    Monday, March 24, 2014 7:37 PM
  • Hello,
    I'm not sure what you are doing with your call to "GetCurrentPadding". There are two suggested ways to drain audio packets out of the current buffer.

    •Alternate calls to GetBuffer and ReleaseBuffer, reading one packet with each pair of calls, until GetBuffer returns AUDCNT_S_BUFFEREMPTY, indicating that the buffer is empty.
    •Call GetNextPacketSize before each pair of calls to GetBuffer and ReleaseBuffer until GetNextPacketSize reports a packet size of 0, indicating that the buffer is empty.

    Using the second method will give you the packet size that you use for your sample rate conversion.
    Also keep in mind that doing a naive multiplication on the 32 bit float values may cause undesirable clipping and aliasing. When down sampling you should always pass your samples through a low pass filter to remove any high frequency data that can't be represented at the lower bitrate. Because of this I would recommend that you "borrow" code from someone that is skilled at writing robust sample rate conversion algorithms.

    I hope this helps,

    James

    Tuesday, March 25, 2014 12:29 AM
  • Hi.

    Thanks for replying. Well, I was being stupid! I was converting the buffer prior to fetch the PCM data from the SIP stack.

    However, I think that converting PCM 16bit to IEEE Float 32 bit and vice-versa will not be an easy task. Also, I think that sometimes WASAPI might not give me the samples in IEEE Float and then it will not work.

    So, do you recommend using XAudio2, right? Are there any samples that you recommend?

    Tuesday, March 25, 2014 3:34 PM