2

I'm debugging with python audio, having a hard time with the audio coding.

Here I have a string full of audio data, say, [10, 20, 100].

However the data is stored in a string variable,

data = "����������������"

I want to inspect the values of this string.

Below is the things I tried

Print as int

I tried to use print "%i" % data[0] ended up with

 Traceback (most recent call last):
   File "wire.py", line 28, in <module>
     print "%i" % data[i]
 TypeError: %d format: a number is required, not str

Convert to int

int(data[0]) ended up with

Traceback (most recent call last):
  File "wire.py", line 27, in <module>
    print int(data[0])
ValueError: invalid literal for int() with base 10: '\xd1'

Any idea on this? I want to print the string in a numerical way since the string is actually an array of sound wave.

EDIT

All your answers turned out to be really helpful.

The string is actually generated from the microphone so I believe it to be raw wave form, or vibration data. Further this should be referred to the audio API document, PortAudio.

After looking into PortAudio, I find this helpful example.

** This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
static int patestCallback( const void *inputBuffer, void *outputBuffer,
                            unsigned long framesPerBuffer,
                            const PaStreamCallbackTimeInfo* timeInfo,
                            PaStreamCallbackFlags statusFlags,
                            void *userData )
{
    paTestData *data = (paTestData*)userData;
    float *out = (float*)outputBuffer;
    unsigned long i;

    (void) timeInfo; /* Prevent unused variable warnings. */
    (void) statusFlags;
    (void) inputBuffer;

    for( i=0; i<framesPerBuffer; i++ )
    {
        *out++ = data->sine[data->left_phase];  /* left */
        *out++ = data->sine[data->right_phase];  /* right */
        data->left_phase += 1;
        if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
        data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
        if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
    }

    return paContinue;
}

This indicates that there is some way that I can interpret the data as float

Bach
  • 6,145
  • 7
  • 36
  • 61
SolessChong
  • 3,370
  • 8
  • 40
  • 67
  • Do you know what number you are expecting in the first position? Is it 209 perhaps? – sberry Apr 08 '14 at 03:49
  • Can you add the output of `print repr(data)` to your question... – sberry Apr 08 '14 at 03:51
  • 3
    Your data is most likely binary, so that means you likely need to use struct to unpack it. How did the data get generated? – sberry Apr 08 '14 at 03:54
  • 1
    +1, this is the proper way to go. If you know how it was packed you can use struct.unpack. In fact my response below will produce the same output as `struct.unpack('48c',data)`, and so it implicitly assumes that the data contains 48 1-byte numbers. – johncip Apr 08 '14 at 04:09
  • Might be helpful: http://stackoverflow.com/questions/3783677/how-to-read-integers-from-a-file-that-are-24bit-and-little-endian-using-python – johncip Apr 08 '14 at 04:16
  • Please see my updates. In some occasions the data could be interpreted as float, as inspired by @sberry – SolessChong Apr 08 '14 at 05:22

4 Answers4

3

To be clear, your audio data is a byte string. The byte string is a representation of the bytes stored in the audio file. You are not going to simply be able to convert those bytes into meaningful values without knowing what is in the binary first.

As an example, the mp3 specification says that each mp3 contains header frames (described here: http://en.wikipedia.org/wiki/MP3). To read the header you would either need to use something like bitstring, or if you feel comfortable doing the bitwise manipulation yourself then you would just need to unpack an integer (4 bytes) and do some math to figure out the values of the 32 individual bits.

It really all depends on what you are trying to read, and how the data was generated. If you have whole byte numbers, then struct will serve you well.

sberry
  • 128,281
  • 18
  • 138
  • 165
1

If you're ok with the \xd1 mentioned above:

for item in data: print repr(item), 

Note that for x in data will iterate over each value in the list rather than its location. If you want the location you can use for i in range(len(data)): ...

If you want them in numerical form, replace repr(item) with ord(item).

johncip
  • 2,087
  • 18
  • 24
0

It is better if you use the new {}.format method:

data = "����������������"

print '{0}'.format(data[3])
sshashank124
  • 31,495
  • 9
  • 67
  • 76
  • It looks fancy, however, I got another chaos character printed out. I want to convert it into a number actually. Let me add this into my question. – SolessChong Apr 08 '14 at 03:45
0

You could use ord to map each byte to its numeric value between 0-255:

print map(ord, data)

Or, for Python 3 compatibility, do:

print([ord(c) for c in data])

It will also work with Unicode glyphs, which might not be what you want, so make sure you have a bytearray or an actual str or bytes object in Python 2.

Attila O.
  • 15,659
  • 11
  • 54
  • 84
  • This is exactly what I wanted at the very begging. However the problem turned out to be interpreting binary data rather than mapping the char to int8. – SolessChong Apr 08 '14 at 05:24
  • Well, can't help you with that… but, for interpreting binary data, it might be faster/easier to use a `bytearray`, or just keep the data as is (a `bytes` instance). – Attila O. Apr 08 '14 at 08:50