MMC MP3 Player

From Nutwiki
Jump to: navigation, search

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.

<source lang="c">

  1. include <cfg/os.h>
  1. include <fs/phatfs.h>
  2. include <sys/timer.h>
  3. include <dev/board.h>
  1. include <cfg/arch/gpio.h>
  2. include <cfg/audio.h>
  1. include <string.h>
  2. include <stdlib.h>
  3. include <stdio.h>
  4. include <fcntl.h>
  5. include <io.h>
  6. include <dirent.h>
  1. define VERSION "1.4.1"
  1. if defined(AT91SAM7X_EK) || defined(AT91SAM9260_EK)
  2. include <dev/hxcodec.h>
  3. else
  4. define CS_HARDWARE_CODEC 1
  5. include <dev/vscodec.h>
  6. 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);

  1. ifdef CS_HARDWARE_CODEC
   NutRegisterSpiDevice(&devSpiVsCodec0, &DEV_SPIBUS, CS_HARDWARE_CODEC);
  1. else
   NutRegisterDevice(&devHelixCodec, 0, 0);
  1. 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;

} </source>

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.

<source lang="c"> 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;

} </source>

Playing a file

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

<source lang="c"> 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;

} </source>

Makefile

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

<source lang="text"> 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)

</source>

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.


Template:Languages