# PDM to PCM audio conversion

**URL:** <https://discuss.pynq.io/t/pdm-to-pcm-audio-conversion/1865>\
**Category:** Support\
**Created:** [October 8, 2020, 3:01pm UTC](https://discuss.pynq.io/t/pdm-to-pcm-audio-conversion/1865 "2020-10-08T15:01:49Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![GZanni](https://avatars.discourse-cdn.com/v4/letter/g/a9adbd/32.png) [@GZanni](https://discuss.pynq.io/u/GZanni)\
**Post date:** [October 8, 2020, 3:01pm UTC](https://discuss.pynq.io/t/pdm-to-pcm-audio-conversion/1865/1 "2020-10-08T15:01:49Z")

</div>

Hi everyone,  
I am currently following the thread on this git repo: [Error in setup · Issue #1 · wady101/PYNQ\_Z2-Audio · GitHub](https://github.com/wady101/PYNQ_Z2-Audio/issues/1) . In this repo there is a modified version of Pynq where I can get directly the audio stream, but I have found that is encoded as PDM, whereas I need PCM encoding. Is there a way to have a conversion to PCM? I have tried to use a lowpass filter but is not working, so I am trying to implement manually a sinc3 filter but it seems not working. Here is the code:

def process(self):

```
    k = 0
    for i in range(0, len(self._input_signal)):
        
        if self._input_signal[i] == 1:
            self._acc1 = self._acc1 + 1
        self._acc2 = self._acc2 + self._acc1
        self._acc3 = self._acc3 + self._acc2
        
        if i == (self._decimation_factor-1)*(k+1):
            self._diff1 = self._acc3 - self._acc3_d2
            self._diff2 = self._diff1 - self._diff1_d
            self._diff3 = self._diff2 - self._diff2_d
            self._acc3_d2 = self._acc3
            self._diff1_d = self._diff1
            self._diff2_d = self._diff2
            self._data[k] = self._diff3
            k = k + 1

    return self._data 

```

Do you have any suggestions?

Thanks in advance,

Guglielmo

---

<div class="post-metadata">

**Author:** ![VicerExciser](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/vicerexciser/32/1643_2.png) [@VicerExciser](https://discuss.pynq.io/u/VicerExciser)\
**Post date:** [October 23, 2020, 12:27am UTC](https://discuss.pynq.io/t/pdm-to-pcm-audio-conversion/1865/2 "2020-10-23T00:27:44Z")

</div>

Unsure if this will work for your case, but this is how I’ve accomplished PDM → PCM/WAV audio translation on the PYNQ-Z1 in the past. It makes use of `numpy` and `scipy`:

> import numpy as np  
> from scipy import signal

> “”"  
> Step 1: Preprocessing  
> In this step, we first convert the 32-bit integer buffer to 16-bit.  
> Then we divide 16-bit words (16 1-bit samples each) into 8-bit words with 1-bit sample each.  
> “”"  
> def preprocess(audio\_buffer):
> 
> > af\_uint8 = np.unpackbits(audio\_buffer.astype(np.int16).byteswap(True).view(np.uint8))  
> > return af\_uint8

> “”"  
> Step 2: Converting PDM to PCM  
> We now convert PDM to PCM by decimation. The sample rate is reduced from 3MHz to 32kHz.  
> We will remove the first and last 10 samples in case there are outliers introduced by decimation.  
> We will also remove the DC offset from the waveform.  
> “”"  
> def convert(af\_uint8):
> 
> > af\_dec = signal.decimate(af\_uint8, 8, zero\_phase=True)  
> > af\_dec = signal.decimate(af\_dec, 6, zero\_phase=True)  
> > af\_dec = signal.decimate(af\_dec, 2, zero\_phase=True)  
> > af\_dec = (af\_dec[10:-10] - af\_dec[10:-10].mean())  
> > return af\_dec

First `preprocess()` must be invoked for a buffer of PDM audio data (for my use case, `audio_buffer` was the singleton AudioDirect IP object’s buffer, accessed as `BaseOverlay('base.bit').audio.buffer`, but perhaps it will work for you by passing your `_input_signal` buffer). So this code may work for you like:

> pcm\_audio = convert(preprocess(self.\_input\_buffer))

I’m not sure if this will, but I hope this can help somewhat.
