MMC MP3 Player

From NutWiki

Jump to: navigation, search

Contents

Test Environments

Hardware
Comments
Nut/OS
4.7.4
Nut/OS
4.8.0
Ethernut 3.0 E requires Medianut Compiler Error NT
EIR 1.0 C OK
Binaries
AT91SAM7X-EK requires Calypso NT NT
AT91SAM9260-EK requires Calypso NT NT
Compiler: ARM-GCC 4.2.2

Description

This is a simple MP3 player. It scans a MultiMedia Card for files with extension .mp3 and sends the contents to an MP3 decoder.

Source Code

This code requires Nut/OS 4.8 or later. Check the page's history (Nov 2008) for previous versions.

Main routine

The main program does some initialization and then enters an endless loop, reading the MMC.

#include <cfg/os.h>
 
#include <fs/phatfs.h>
#include <sys/timer.h>
#include <dev/board.h>
 
#include <cfg/arch/gpio.h>
#include <cfg/audio.h>
 
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <dirent.h>
 
#define VERSION     "1.4.1"
 
#if defined(AT91SAM7X_EK) || defined(AT91SAM9260_EK)
#include <dev/hxcodec.h>
#else
#define CS_HARDWARE_CODEC   1
#include <dev/vscodec.h>
#endif
 
static int ScanFolder(char *root);
static int PlayFile(int fd);
 
int main(void)
{
    u_long baud = 115200;
    int volid;
 
    NutRegisterDevice(&DEV_DEBUG, 0, 0);
    freopen(DEV_DEBUG_NAME, "w", stdout);
    _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
    puts("\nNut/OS MMC MP3 Player " VERSION);
 
#ifdef CS_HARDWARE_CODEC
    NutRegisterSpiDevice(&devSpiVsCodec0, &DEV_SPIBUS, CS_HARDWARE_CODEC);
#else
    NutRegisterDevice(&devHelixCodec, 0, 0);
#endif
    NutRegisterDevice(&devPhat0, 0, 0);
    NutRegisterDevice(&DEV_MMCARD, 0, 0);
 
    for (;;) {
        for (;;) {
            printf("Card...");
            if ((volid = _open(DEV_MMCARD_NAME ":1/PHAT0", _O_RDWR | _O_BINARY)) != -1) {
                puts("ready");
                break;
            }
            puts("not found");
            NutSleep(2000);
        }
        ScanFolder("PHAT0:/");
        _close(volid);
    }
    return 0;
}

At the top all required header files are included.

The MP3 Player can either use a hardware decoder chip or do decoding by software.

Scanning a folder

The following routine scans a specified folder for MP3 files.

static int ScanFolder(char *root)
{
    int rc = 0;
    DIR *dir;
    int fd;
    char *path;
 
    printf("Scanning %s\n", root);
    dir = opendir(root);
    if(dir) {
        struct dirent *dep;
 
        path = malloc(256);
        while(rc == 0 && (dep = readdir(dir)) != NULL) {
            if (strcmp(dep->d_name, ".") && strcmp(dep->d_name, "..")) {
                if (dep->d_type) {
                    strcpy(path, root);
                    strcat(path, dep->d_name);
                    strcat(path, "/");
                    rc = ScanFolder(path);
                } else {
                    char *cp = strrchr(dep->d_name, '.');
                    if (cp && stricmp(cp, ".mp3") == 0) {
                        strcpy(path, root);
                        strcat(path, dep->d_name);
                        sprintf(path, "%s%s", root, dep->d_name);
                        printf("Playing %s\n", path);
                        fd = _open(path, _O_RDONLY | _O_BINARY);
                        if (fd == -1) {
                            rc = -1;
                        } else {
                            rc = PlayFile(fd);
                            _close(fd);
                        }
                    }
                }
            }
        }
        closedir(dir);
        free(path);
    }
    return rc;
}

Playing a file

The routine PlayFile expects a file handle of an opened MP3 file and streams its contents to the audio decoder driver.

static int PlayFile(int fd)
{
    int codec;
    uint8_t *mp3buff;
 
    codec = _open("audio0", _O_WRONLY | _O_BINARY);
    if (codec == -1) {
        printf("No codec\n");
        return -1;
    }
 
    mp3buff = malloc(512);
    for (;;) {
        int got;
        uint8_t *bp;
 
        bp = mp3buff;
        got = _read(fd, bp, 512);
        if (got <= 0) {
            break;
        }
        while (got) {
            int sent;
 
            sent = _write(codec, bp, got);
            if (sent < 0) {
                break;
            }
            if (sent == 0) {
                NutSleep(1);
            } else {
                got -= sent;
                bp += sent;
            }
        }
    }
    free(mp3buff);
    _close(codec);
 
    return 0;
}

Makefile

Here's the Makefile to build the MP3 player. Note, that the spaces before -rm -f $... have to be tabs instead of spaces.

PROJ = cs_mp3mmc
 
include ../Makedefs
 
SRCS =  $(PROJ).c
OBJS =  $(SRCS:.c=.o)
LIBS =  $(LIBDIR)/nutinit.o -lnutfs -lnutos -lnutcrt -lnutdev -lnutarch -lnutcontrib
TARG =  $(PROJ).hex
 
all: $(OBJS) $(TARG) $(ITARG) $(DTARG)
 
include ../Makerules
 
clean:
        -rm -f $(OBJS)
        -rm -f $(TARG) $(ITARG) $(DTARG)
        -rm -f $(PROJ).obj
        -rm -f $(PROJ).map
        -rm -f $(SRCS:.c=.lst)

See also

External Links

  • C file input/output The C programming language provides many standard library functions for file input and output.
  • MP3 MPEG-1 Audio Layer 3, more commonly referred to as MP3, is a digital audio encoding format using a form of lossy data compression.


Personal tools