Sunday, 23 November 2008

Progress with MusicPal Sound Programming

After a couple of hours of using strace to try to understand what Nashville was doing, and looking at the "base_audio" directory in the MusicPal kernel source directory, I have finally got it to make a noise.

Basically you have to use /dev/audio and send some ioctl's to initialise the hardware, and set up the graphic equaliser. You can then write raw data to /dev/audio just like you would with OSS. In fact, I used the OSS sinegen.c example program as the basis and just altered the ioctls. http://www.musicpal.webhop.net/audiotest.c is my sample program (it needs audio.h from the MusicPal kernel source code to compile) - it makes a continuous tone come out of the MusicPal speaker, which is progress! There are some comments in the code to show what it is doing (as far as I can work out anyway!).

11 comments:

  1. Where can I download the audio.h needed to compile audiotest.c?

    ReplyDelete
  2. ah, ok I did look in the kernel source but it seems I was looking at the vanilla EDLK kernel source not the MusicPal kernel source which has to be downloaded separately. Anyway audio.h also references audiotypes.h, so After I found both these files the audiotest.c file compiles successfully, however I was unable to get a sound out of my Music Pal perhaps you could provide some usage instructions?

    ReplyDelete
  3. More progress, did some fiddling and got audiotest to produce a nice test tone.

    Then I did the following. On a Linux box run

    mpg123 -s music.mp3 | nc -l -p 1234

    Telnet to MusicPal and do

    ./audiotest
    ctrl+c

    nc <LinuxBoxIP> 1234 > /dev/audio

    Woah music playing! unfortunately it only plays on the MusicPals builtin speaker and not the HIFI that I have attached to my MusicPal

    ReplyDelete
  4. That is real progress - the sine wave is not good to listen to!
    Does audiotest play through your hifi, or just through the MusicPal speakers? I'll have a dig through the Kernel source code for how to switch the external outputs on and off - I think the audiotest.c program has a line that I said I did not understand - the nashville MusicPal program does an extra ioctl that does not seem to be necessary - it might be enabling the audio outputs. I'm having trouble with my internet connection so can't check, but the sound mixer in the MusicPal is an obscure string of letters and numbers, and it has a driver in the kernel source tree if you want to have a look.

    NT

    ReplyDelete
  5. I have just had another go at it, and I think you might need the main nashville application to play something before audiotest works? Is that what you found?
    If that is the case we are not initialising the audio output correctly - presumably the AUDIO_SET_WOLFSON_REG call in audiotest.c is incorrect. The comment above it points to the datasheet for the mixer chip if you want to try to work out what we should do - I've just got to make a bit of progress on a little Christmas present before I get back to it!

    ReplyDelete
  6. I compiled and ran strace and noticed, that nashville opens /dev/audio twice, once in read/write mode, and once in write only mode. The fd for the rw was 6 so you can see the respective ioctl's against this fd:

    ioctl(6, 0x40047015, 0xbec16ca8) = 0
    ioctl(6, RTC_PLL_SET, 0xbec16ca8) = 0
    ioctl(6, 0x40047013, 0xbec16c2c) = 0
    ioctl(6, 0x40047013, 0xbec16c2c) = 0

    these numbers didn't make alot of sense to me until I translated them into the numbers defined in audio.h

    so you can see these translated here:


    ioctl(6, AUDIO_SWITCH_OUTPUT, 0xbec16ca8) = 0
    ioctl(6, AUDIO_GET_WOLFSON_REG, 0xbec16ca8) = 0
    ioctl(6, AUDIO_SET_VOLUME, 0xbec16c2c) = 0

    I used the following program to get these:

    giles@korma:~/MusicPal$ cat iow.c
    #include <linux/ioctl.h>

    main()
    {
    int i;
    for(i = 0;i<255; i++)
    printf("I=%d IOW=%x\n",i,_IOW('p',i,unsigned long));
    }

    ReplyDelete
  7. Your work with the MusicPal is very interesting ... keep up the good work!

    It will be very interesting to see what the outcome of all this research bears.

    ReplyDelete
  8. Wow - you have made much more progress than me - I saw all of that extra stuff in the strace output, but haven't had chance to try to decode it - it looks like you have it cracked, well done!

    ReplyDelete
  9. Hi,

    to decode the struct, you can write a preloaded library that overrides ioctl():

    /*
    ##############
    # preload.c
    ##############
    */
    #include < stdio.h>
    #include < stdlib.h>
    #include < stdarg.h>
    #include < dlfcn.h>
    #include < time.h>
    #include "linux/ioctl.h"
    #include "audio.h"

    static char * libc = "/lib/libc.so.6";

    static void * dl;
    static int (* org_ioctl)(int, unsigned long int, void*data);

    int ioctl(int fd, int request, void *data)
    {
    int retval = -1;

    if(org_ioctl == NULL)
    {
    dl = dlopen(libc, RTLD_NOW);
    org_ioctl = dlsym(dl, "ioctl");
    }

    if(request == _IOW(AUDIO_IOC_MAGIC,11, unsigned long))
    {
    wm8971_reg *reg = (wm8971_reg*)data;
    printf("fd: %d, req: %x, data: %x, addr: %d, val: %d\n", fd, request, data, reg->addr, reg->value);
    }

    return org_ioctl(fd, request, data);
    }

    #########################

    Compile:
    arm-linux-gcc -ldl -fPIC -shared -o preload.so preload.c

    Run:
    LD_PRELOAD=/tmp/preload.so /bin/nashville

    ReplyDelete
  10. Now that is impressive - I didn't know you could do that - This looks like a method of overriding any function in a shared library isn't it? This means that we can work out what the nashville application is doing to set-up the hardware, which will be handy.

    I will get back to thinking about the MusicPal soon - just got a couple of other jobs to do first......

    ReplyDelete
  11. Well done - I'll have a play with that.
    I put links to your work and that of giles above in a separate post so they do not get lost.

    ReplyDelete