• AVR Freaks

USB MP3 Audio Streamer

Page: 12 > Showing page 1 of 2
Author
andyolivares
Junior Member
  • Total Posts : 118
  • Reward points : 0
  • Joined: 2006/11/29 07:46:48
  • Location: 0
  • Status: offline
2009/07/08 18:04:13 (permalink)
0

USB MP3 Audio Streamer

Hi guys:

I need some help here. I need to create something I call "USB MP3 Audio Streamer". The basic idea is a device that gets data from USB (using the HID class), send it to a VS1011e MP3 decoder and play.
I've been trying with a PIC18LF2550 with bad results. I think my problems are that the speed in which the data needs to be sent to the MP3 decoder is very fast, and that the USB using the HID class is kind of slow.

So... i need some help here, because I need someone to tell me what can I use instead. I've been thinking on PIC32... is it rapid enough to get MP3 data trough the USB using the HID class (I really need it to be HID, as I need no drivers), decode the MP3 data and send it to some audio codec?

Does anybody knows a better solution? I've been thinking on embedded devices also, like an ARM microprocessor running some version of Linux or something.

I'm really lost here, so any help will be greatly appreciated.

Best regards,

Andy

PD: I need to use MP3 because I need the device to use as less USB bandwidth as possible.

Visit my website: http://www.andyolivares.com
You might find useful projects and example codes.
#1

37 Replies Related Threads

    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 18:19:53 (permalink)
    0
    HID will not work. Full speed USB HID device (which uses interrupt transfer) will have the theoretical maximum speed at 64B/ms or 64000 B/s. That will not be able to sustain any decent MP3 data transfer.

    It is better you implement USB Audio device.

    Mike Zoran has a good example here:
    http://www.raccoonrezcats.com/soundcard.html

    More discussions here:
    http://forum.microchip.com/tm.aspx?m=231496

      USB_Links and libusb
    #2
    andyolivares
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2006/11/29 07:46:48
    • Location: 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 18:26:04 (permalink)
    0
    Well, as I said, I need to use no drivers, that's why I needed the HID class. So, using the USB Audio Class will I need drivers? If no... can I connect many of these devices to a single USB hub and play different music in each one?
    The reason I need to transfer MP3 data is because of the bandwidth. I need to connect multiple devices to the same bus, and I though using MP3, was the best approach.

    Please tell me if I'm wrong.

    Thank you for quick reply.

    Andy

    Visit my website: http://www.andyolivares.com
    You might find useful projects and example codes.
    #3
    FunnyNYPD
    Super Member
    • Total Posts : 1553
    • Reward points : 0
    • Joined: 2007/09/28 20:06:59
    • Location: USA & Canada
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 18:36:59 (permalink)
    0
    The no driver idea is great and useful to end users.
    #4
    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 19:02:01 (permalink)
    0
    You do not need drivers for standard USB audio device. Major OS like Windows, Linux and Mac OS X should support standard USB audio class device right out of the box.

    As for using multiple USB audio device at the same time, it should be ok but it might depend on the host software.

      USB_Links and libusb
    #5
    andyolivares
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2006/11/29 07:46:48
    • Location: 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 19:19:08 (permalink)
    0
    And what about the bandwidth usage of the device? Should I be able to connect multiple devices with no bandwidth problems? What I don't understand quite well is how the OS sends the audio data to the microcontroller... as uncompressed audio samples?

    Thank you all.

    Andy

    Visit my website: http://www.andyolivares.com
    You might find useful projects and example codes.
    #6
    mzoran
    Super Member
    • Total Posts : 683
    • Reward points : 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 21:14:57 (permalink)
    0
    Hi Andy,

    I can offer some help, but I really don't want to get too involved in this project. I'm currently busy with a bunch of things. And it's summer timeSmile

    I think HID does has enough bandwidth to handle MP3. If I'm not mistaken, HID is 64,000 bytes/s which is 512,000 bits/second. Tolerable(IMHO) constant bitrate MP3 is 128kbps. So I think you are OK by a factor 4.

    But, since you are doing things in user mode, you need to be care that you keep all the frames full. If you don't have a buffer of data ready by the start of the next frame, you loose for the whole frame. Also, interrupt endpoints have a polling interval. Some of the Microchip examples set this to a high value. You need to set this to 1 in the endpoint descriptor so that the PC will poll the endpoint to see if it's able to accept data every frame. You may have to use asynchronous I/O on the PC side and always keep multiple writes pending to keep the pipe busy.

    Instead of the 18FLF2550, you may want to consider the newer 18F26J50. It's native 3.3V just like the MP3 chip so it will run at the full 48MHz. It also is available in DIP just like the 2550. Except for the configuration registers, it's mostly C level compatible with the 2550.

    I think the USB audio standard supports compressed audio formats like MP3, but I'm not sure the in the box Windows driver supports it.




    #7
    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 21:48:48 (permalink)
    0
    Adding problems to the HID is that sometimes 1ms polling interval is not really honored by Windows. You might get 2ms even if you specified 1ms polling interval. There are reports that you can get 1ms always working but my past testing did not prove that yet.

      USB_Links and libusb
    #8
    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 21:51:52 (permalink)
    0
    This is my past test about the 1ms polling interval using Jan Axelson's generic HID example. The host program may play a part though.
    http://www.microchip.com/forums/tm.aspx?m=337818

      USB_Links and libusb
    #9
    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 22:29:30 (permalink)
    0
    ORIGINAL: mzoran
    I think the USB audio standard supports compressed audio formats like MP3, but I'm not sure the in the box Windows driver supports it.

    Hmm, isn't this handle by the PC host software (audio playing software) for USB audio device and not the driver?

      USB_Links and libusb
    #10
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 22:36:34 (permalink)
    0
    Xiaofan, yes, unless driver quietly decodes mp3 and forwards uncompressed data to hardware.

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #11
    mzoran
    Super Member
    • Total Posts : 683
    • Reward points : 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/08 23:36:56 (permalink)
    0
    No, the spec actually supports passing compressed data on the USB bus. The idea is that the device will have a hardware decoder built out of specialized components that can do a better job then the CPU. Remember, USB audio is very old from at least the mid 1990's where more compression of audio and video was done with hardware.

    The same concept is used with HDMI. The TV can support different compressed formats in case the TV has better equiptment then the DVD/BlueRay player.

    ActiveMovie( one of the multimedia frameworks of Windows) actually supports this. This is no different then a NVIDA video card supporting hardware assisted MPEG-2 decoding and video processing.

    Some of the compressed formats mentioned in the spec are MPEG and AC-3.

    But I don't think the in the box usbaudio.sys driver supprts anything other then PCM.
    post edited by mzoran - 2009/07/08 23:45:01
    #12
    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/09 01:22:09 (permalink)
    0
    I have not done too much research on the USB audio. But here is an MSDN entry.

    http://msdn.microsoft.com/en-us/library/ms789375.aspx

    USBAudio Class System Driver The USBAudio class system driver (Usbaudio.sys) is an AVStream minidriver that provides driver support for USB Audio devices that comply with the Universal Serial Bus Device Class Definition for Audio Devices (release 1.0). This specification is available at the USB Implementers Forum Web site. The USBAudio driver supports a subset of the features that are described in the USB Audio specification.
    The USBAudio driver for Windows 98 introduced support for USB devices such as speakers and microphones. Support for MIDI devices was added in Windows Me.
    When an audio device identifies itself as USB Audio-compliant during Plug and Play device enumeration, the system automatically loads the USBAudio driver to drive the device. USBAudio drives the device directly, without the aid of a proprietary adapter driver. This means that a device that complies with the USB audio specifications requires no proprietary adapter driver.
    Microsoft recommends that hardware vendors use the USBAudio driver for their USB Audio devices instead of writing proprietary adapter drivers.
    In Windows 98, the USBAudio driver supports the following features:
    • All Type I formats (except 8-bit signed PCM)
    • AC-3 Type II format
    • Synchronization types synchronous and adaptive
    • Multichannel devices
    However, USBAudio in Windows 98 does not support:
    • 8-bit signed PCM format
    • MPEG Type II format
    • Type III formats
    • USB MIDI
    • WAVEFORMATEXTENSIBLE wave format (USBAudio uses packed WAVE_FORMAT_PCM for 24-bit data instead.)
    In Windows 98 Second Edition (SE), Windows Me, and Windows 2000 and later, USBAudio supports all the same features as Windows 98, with one exception: USBAudio supports WAVEFORMATEXTENSIBLE but does not support packed WAVE_FORMAT_PCM for 24-bit data.
    In Windows Me, and Windows XP and later, USBAudio supports all the features that are supported in Windows 98 SE and Windows 2000. In addition, Windows Me and Windows XP support USB MIDI but do not support USB MIDI Elements.
    The following figure shows the driver hierarchy for a USB audio device. All of the driver components shown in the figure are provided by Microsoft with the operating system.

    Driver Hierarchy for a USB Audio Device



      USB_Links and libusb
    #13
    andyolivares
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2006/11/29 07:46:48
    • Location: 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/10 23:09:22 (permalink)
    0
    Well, as mzoran mentioned before, it may be possible to send the appropiate amount of MP3 data using the HID class (as don't see any mention to MP3 in the USB Audio specification). The problem here (I think) resides in synchronizing all the processes to play the MP3 data.
    I've been trying the VS1011e for some time. It is a very good chip. But PIC18LF2550 doesn't seem to be a good candidate for such a heavy load. I've been trying to get MP3 data from an SD memmory card, putting the data in a buffer (512 bytes) in the PIC's RAM and send it to the MP3 decoder chip. It seems that this "simple" process is too much for a PIC18LF2550 as I hear cropped sound. I tried to do this a LOT of different ways and my conclusion remains: this PIC is not capable even running at full 48 Mhz.
    The weird thing is that if I assert the SD card, send the appropiate command to get a sector, wait for the data token and let the MP3 decoder chip "hear" the data outputting the SD card directly, it sounds good event at high rates of 320 Kbps. So, my conclusion is that the SD card SPI interface is WAY faster than the SPI module of the PIC. Am I wrong? What do you guys think?

    Andy

    BTW: I'm using CCS compiler version 4.038
    post edited by andyolivares - 2009/07/10 23:13:21

    Visit my website: http://www.andyolivares.com
    You might find useful projects and example codes.
    #14
    mzoran
    Super Member
    • Total Posts : 683
    • Reward points : 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/12 19:46:10 (permalink)
    0
    The PIC SPI has more then enough speed for your application. It took me alot of optimization to get 48KHz 12bit stereo( 1.5Mbps ) working on my device with a 48MHz 18F2550, but it is possible.

    When using SPI, you need to interleave things between the wait states of the SPI module. Don't bother checking SSPIF, just hardcode the number of cycles.

    I've attached the SPI relavant code from my device.

    Also, if possible maybe you should really try the 18F26J50. It's just like the 2550, but it's native 3.3V so you can run it at 48MHz when powered by 3.3V and still be in spec. It also reduces the need for level shifters because I understand your MP3 chip runs at 3.3V. It's available in DIP so you can test things out on a breadboard. It's also cheaper then the 2550.

    The 18F26J50 has a few other enhancements such as DMA for the second SPI module. That way you can load up a big buffer of data, and then send it in one shot to the MP3 chip without needing any CPU interaction freeing the CPU to do other things.

    	

    static U16 UnsignedSample1;
    static U16 UnsignedSample2;
    static unsigned char Drain;

    PIR1bits.TMR2IF = 0;

    #if ( HWVER == 10 )
    //
    // Note that left and right channels
    // are swapped on the audiostreamer 1.0 board
    // DAC 0 is right and DAC 1 is left
    #endif

    UnsignedSample1.u.ushort = 0x8000;
    UnsignedSample1.u.ushort += (unsigned short)*(signed short*)CurrentByte;

    // round instead of truncating the data
    // this generates less noise

    if ( UnsignedSample1.u.ushort & 0x0008 )
    UnsignedSample1.u.ushort += 0x0008;

    UnsignedSample1.u.ushort >>= 1;
    UnsignedSample1.u.ushort >>= 1;
    UnsignedSample1.u.ushort >>= 1;
    UnsignedSample1.u.ushort >>= 1;
    #if ( HWVER >= 12 )
    UnsignedSample1.u.ubytes.highbyte |= 0b10010000;
    #elif ( HWVER == 11 )
    UnsignedSample1.u.ubytes.highbyte |= 0b00010000;
    #else
    UnsignedSample1.u.ubytes.highbyte |= 0b10010000;
    #endif
    CurrentByte += 2;


    // TotalSamplesPlayed++;

    LDACCS = 0;

    // interleave channel operations in with shifting out data through SPI

    SSPBUF = UnsignedSample1.u.ubytes.highbyte;

    // this operation needs to take 9 cycles or more
    UnsignedSample2.u.ushort = 0x8000;
    UnsignedSample2.u.ushort += (unsigned short)*(signed short*)CurrentByte;

    // round instead of truncating the data
    // this generates less noise

    if ( UnsignedSample2.u.ushort & 0x0008 )
    UnsignedSample2.u.ushort += 0x0008;

    Drain = SSPBUF;

    SSPBUF = UnsignedSample1.u.ubytes.lowbyte;

    // this operation needs to take 9 cycles or more
    UnsignedSample2.u.ushort >>= 1;
    UnsignedSample2.u.ushort >>= 1;
    UnsignedSample2.u.ushort >>= 1;
    UnsignedSample2.u.ushort >>= 1;
    #if ( HWVER >= 12 )
    UnsignedSample2.u.ubytes.highbyte |= 0b10010000;
    #elif ( HWVER == 11 )
    UnsignedSample2.u.ubytes.highbyte |= 0b10010000;
    #else
    UnsignedSample2.u.ubytes.highbyte |= 0b00010000;
    #endif
    CurrentByte += 2;

    Drain = SSPBUF;

    LDACCS = 1;

    RDACCS = 0;

    SSPBUF = UnsignedSample2.u.ubytes.highbyte;
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();


    Drain = SSPBUF;

    SSPBUF = UnsignedSample2.u.ubytes.lowbyte;
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();
    Nop();

    Drain = SSPBUF;

    RDACCS = 1;

    LDAC = 0;
    Nop();
    LDAC = 1;

    #15
    andyolivares
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2006/11/29 07:46:48
    • Location: 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/12 20:32:31 (permalink)
    0
    Hi mzoran (can I know your real name?)... really thank you! You have been of great help.

    I'm using the PIC18LF2550 where the "L" comes from "Low voltage" (I guess), so my chip is a native 3.3V device. No level-shift converters are involved.

    I also thought that doing the SPI "the hard way" could save me a LOT of clock cycles. The way I'm planning to do things is as follow:

    1) Check if a packet has come from the USB (the HID class says I can receive a maximum of 64 bytes each 1ms, so I think I'm going to be fine from the USB part).
    2) Get the packet to a temporary array of 64 bytes.
    3) Save the packet to a FIFO buffer implemented using an external SPI SRAM (from Microchip...actually a 23K256).

    All these three steps could be implemented in the main loop. Also I'm planning to configure one of the PIC timers (Timer0, 1, 2?) to make an interrupt every approx 10 ms (sending 512 bytes each 10ms should ensure a playback of 320 Kbps Mp3 streams). So, in this interrupt routine I'm planning to:

    1) Check if I have enough bytes in the FIFO buffer.
    2) Get a burst of bytes from the FIFO buffer (maybe 512 bytes is a good number?).
    3) Update the FIFO's head and tail pointers.
    4) Send the data stream from the FIFO buffer to the VS1011e MP3 decoder chip using the (second?) SPI module of the PIC.

    I don't know if I should disable interrupts (at least the Timer one) when entering the interrupt routine to prevent reentrancy?

    Well, that's my idea. I don't know if you have some advices. ;)

    By the way, I'm using the CCS PIC-C compiler, so I think I will need to modify your code a little bit (what compiler are you using?). I'm using this compiler because I'm very used to it, that's all.

    Again, thank you so much for your help. It is very appreciated.

    Andy

    Visit my website: http://www.andyolivares.com
    You might find useful projects and example codes.
    #16
    mzoran
    Super Member
    • Total Posts : 683
    • Reward points : 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/12 21:27:50 (permalink)
    0
    My real name is Mike Zoran( hence mzoran ). I'm the one who made the USB Audio Streamer and the www.raccoonrezcats.com website which xiaofan refered to in a previous reply.

    Your 18LF2550 is out of spec at 48MHz. If you read the documentation, you will find that the maximum reliable speed for a 2550 running at 3.3V is 16MHz. The only difference between the F and LF part from my understanding is that the LF has been factory tested at 3.3V. Neither part is guaranteed to work reliably above 16MHz at 3.3V. That may be part of the reason you are having reliability problems.

    I think I understand your scheme, but I don't think you need a circular FIFO or the external SRAM. If you stick with the 2550( which is going to require level shifters to run at 48MHz ), you can declare two 512 byte buffers. One in USB ram and the other in general purpose RAM. As the USB data arrives, simply increment the address pointer in the endpoint buffer descriptor by 64 bytes until the buffer is full, then memcpy the buffer over to the GP ram and reset the endpoint address pointer. You can shift the GP RAM out the SPI port in a big burst. If you use CBR MP3, I would expect the data would need to be shifted out at regular intervals.

    The 2550 only has one hardware SPI port. THe 18F26J50 has two.

    Well, that's my two cents. If I'm slow to add more replies on this topic, it's because I've basically said all that I have to add.

    #17
    bien_van_khat
    Starting Member
    • Total Posts : 45
    • Reward points : 0
    • Joined: 2006/05/11 20:41:17
    • Location: Vietnam
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/12 21:30:05 (permalink)
    0
    IMO, the best way to feed the VS10xx decoder is polling its DREQ pin, and feed 32bytes when it becomes active

    if you want to decode 320Kbps mp3 data, you should send 32 bytes over SPI every 0.8ms

    Max SPI clock rate of VS1053b is CKLI/4 for Write operation (I have not yet seen Vs1011 datasheet), about 6MHz. So it takes about 43us to send 32bytes.

    The goal here is to keep the VS10xx 2048-byte FIFO from depleted, so try feeding it when it is possible.

    - first, keep filling your local buffer, when it's full, start feeding the VS, and make this "task" higher priority then USB "task"
    - since you have big local buffer with lot of data already, and the data rate from USB expected to be much higher then data to VS10xx so i think it's able to keep the VS playing smoothly.
    #18
    andyolivares
    Junior Member
    • Total Posts : 118
    • Reward points : 0
    • Joined: 2006/11/29 07:46:48
    • Location: 0
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/12 21:39:38 (permalink)
    0
    Hey! I never read that part of the documentation (even when I read the documentation a lot of times). That maybe that is the reason why I can't read the SD card and send it to the MP3 decoder without glitches.
    I'll definitively get a PIC18F26J50 and run it at full 48Mhz. I kind of feel stupid right now. All this time wondering WHY if "running at 48Mhz with my PIC18LF2550" it was too slow to make simple processes.

    Well, I hope to get my new PIC as soon as possible to start trying.

    I think I'll try to make this as simple as possible at the begining:

    1) Get a 64-bytes packet from USB
    2) Check if the data request line of the VS1011e is high
    3) If it is high, feed the decoder chip with MP3 data
    4) If not high, wait until high
    5) Repeat the whole process (at step 1)

    I think this simple process with correct speed, should work flawlessly.

    Again and again, thank you for your help.

    Andy

    Visit my website: http://www.andyolivares.com
    You might find useful projects and example codes.
    #19
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    RE: USB MP3 Audio Streamer 2009/07/12 21:50:44 (permalink)
    0
    Hi Andy,

    As of SD card,
    The weird thing is that if I assert the SD card, send the appropiate command to get a sector, wait for the data token and let the MP3 decoder chip "hear" the data outputting the SD card directly, it sounds good event at high rates of 320 Kbps. So, my conclusion is that the SD card SPI interface is WAY faster than the SPI module of the PIC.

    In this configuration, the sound data is directly passed from the SD card to the VS1011e over SPI. When the PIC is placed in-between, the sound data travels over the SPI bus twice, from the SD to the PIC, and then from the PIC to the VS1011e. The actual transfer speed is reduced to the half.

    But I don't think the problem lies in the clock (SCK) speed of the SPI (MSSP) module. It goes up to 12MHz at 48MHz Fosc. Of course, the faster is better - SD card accepts up to 25MHz. But for VS1011e, the clock speed is limited to around 4 MHz (CLKI / 6). You may need to switch the SPI clock speed, for SD and for VS1011e. Or, as mzoran suggested, apply a PIC with two SPI (MSSP) modules.

    The problem lies in the overhead of the file system on the SD card.
    To determine the start block (sector) of the sound data on the SD, the PIC has to read out the directory and the FAT on the SD first. And then, the direct access to the block of the sound data starts. This overhead repeats for every cluster. An on-RAM cache of the FAT accelerates this process.

    On the SD, a cluster occupies contiguous blocks (sectors) of the cluster size. Using Multiple Block Read, you can reduce the command - response overhead of repeated Single Block Reads. It means more RAM for the cluster buffer, 4K bytes or so.

    "How To Determine Your Hard Disks Cluster Size" on MS support on-line
    http://support.microsoft.com/kb/140365

    In these reasons, you'll need large cluster buffers, for FAT and Multiple Block Read.
    PIC18F2550 is not good for your project, because of its small on-chip RAM size, 2K bytes.

    Tsuneo
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5