Writing audio data to SD card via Serial Port without File IO

I currently have a design where a microcontroller reads audio data via SPI interface and writes to the SD card. I am currently generating 600KB file every minute. I am roughly writing at 10KB/sec.

I have to migrate my design to an Arduino Yun for several. I am using this Yun shield + Arduino Mega 2560 board. Since the SD card is not interfaced to the microcontroller on the Yun, I will have to write this via serial port.

I tried the File IO class of the Arduino Bridge. and it seems to be slow for requirements (it took 12 seconds to load a 40KB plugin. It takes only 2.15 seconds in my current design).

I did some web searches and I ran into these threads : Thread-1, Thread-2, Thread-3.

I have concluded that I have to write my own application with message header, CRC check etc at both the linux ends. I have a couple of questions:

  1. Has someone tried writing their own UART-SD interface for the Yun? (I could avoid re-inventing the wheel)

  2. At 115200 or 230400 bps, is it possible to write at approximately 10 kB/s with all the CRC check, message header etc?

  3. According to the Atmega2560 datasheet, the microcontroller is capable of transmitting data via the UART interface at 1M bps when it is operated at 16 MHz. ( I have personally tried this with an Atmega328). Is the bootloader necessary for remote upload of hex files if it is compiled in Atmel studio?

Which route is better? Custom serial port API implemented in an Arduino sketch or code written in Atmel studio?

fat16lib wrote some code last summer that captures mono audio from SPI ADC and writes it to SD card at 44.1KHz rate (CD audio rate). I am going to use it capture audio samples for an electronic drum. It also can play files back from SD card at same rate. If I can find the topic I'll post it. [Edit]: Here it is: http://forum.arduino.cc/index.php?topic=180769.0

My Bobuino2 card started out to support that (and it will incorporate it all eventually, got usurped for more urgent needs before I had the ADC/DAC parts done). I'll add the ADC/DAC to the prototype area this summer and get back to testing. http://www.crossroadsfencing.com/BobuinoRev17/ |500x296

yamanoorsai_15: I currently have a design where a microcontroller reads audio data via SPI interface and writes to the SD card. ...

What type audio data? Is it I2S (Integrated Interchip Sound) or MP3 file or analog audio with ADC/SPI interface?

yamanoorsai_15: ... I am currently generating 600KB file every minute. I am roughly writing at 10KB/sec. ...

If file format is MP3 (average compression ratio is 10:1), generating 60KB file every minute, roughly writing at 1KB/sec.

If the interface is SPI, there may be another solution: do it all on the Linux side. I don't know about the Yun Shield, but on the actual Yun board the SPI lines from the AVR processor are also connected to the Linux processor (it's how the Linux side loads a sketch into the AVR.)

Perhaps you can just collect the data from the SPI interface directly on the Linux side, and have it write to the SD card with no serial communications needed? Here are a couple threads where one poster was able to do SPI directly from Linux:

Dragino Yun shield use same software base as Yun.

The Dragino Yun shield's SPI lines from the AVR processor are also connected to the Linux processor (it's how the Linux side loads a sketch into the AVR.)

Perhaps you can just collect the data from the SPI interface directly on the Linux side, and have it write to the SD card with no serial communications needed? Here are a couple threads where one poster was able to do SPI directly from Linux:

http://forum.arduino.cc/index.php?topic=325246.0
http://forum.arduino.cc/index.php?topic=326355.0

I did not think of this. Let me look into it.

What type audio data? Is it I2S (Integrated Interchip Sound) or MP3 file or analog audio with ADC/SPI interface?If file format is MP3 (average compression ratio is 10:1), generating 60KB file every minute, roughly writing at 1KB/sec.

SPI. I am using a VS1053 encoder. It is controlled via SPI.

Plan B:

Use USB sound card:

If use Yun then powered USB hub is needed. Dragino is not required powered USB hub

opkg update
opkg install kmod-sound-core 
opkg install kmod-usb-audio 
opkg install alsa-utils
arecord -d 60 -f S8 -r 22050 /mnt/sda1/test.wav

By pass ATmega32u4 completed.

sonnyyu: Plan B:

Use USB sound card:

If use Yun then powered USB hub is needed. Dragino is not required powered USB hub

opkg update
opkg install kmod-sound-core 
opkg install kmod-usb-audio 
opkg install alsa-utils
arecord -d 60 -f S8 -r 22050 /mnt/sda1/test.wav

By pass ATmega32u4 completed.

This is a great idea. I tried this out. I keep getting these warning/errors:

I got the following warnings/errors when I try to record audio using the USB audio card:

overrun!!! (at least 609243942.341 ms long) overrun!!! (at least 609243944.282 ms long) overrun!!! (at least 609243942.341 ms long)

It is bug of arecord ?! I found some kind of work around:

nano record.sh
#!/bin/ash
arecord -d 60  -f U8 -r 22050 /tmp/test.wav
mv /tmp/test.wav /mnt/sda1/
chmod 755 record.sh
./record.sh

Basic concept is first save into RAM then move to flash, It fixed overrun!!! problem, but met second bug. arecord keep send out SIGHUP and SIGTERM signal.

It did work out. Thanks. When did you receive this error?

Received SIGHUP or SIGTERM

I am not sure what it means but I got it only when I tried to edit the shell script.

yamanoorsai_15: It did work out. Thanks. When did you receive this error?

Received SIGHUP or SIGTERM

I am not sure what it means but I got it only when I tried to edit the shell script.

SIG* are Unix/Linux signals that the OS (operating system) transmits to allow programs to catch the signal and take appropriate action.

https://en.wikipedia.org/wiki/Unix_signal#POSIX_signals

Plan C:

opkg update
opkg install ffmpeg
opkg install lame-lib
 arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Set [C-Media USB Headphone Set], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
 ffmpeg  -y -f alsa -acodec pcm_s16le -ac 1 -ar 44100 -i hw:0,0,0 -t 60 -acodec mp2 /mnt/sda1/output.mp3
nano  record.sh
#!/bin/ash
ffmpeg  -y -f alsa -acodec pcm_s16le -ac 1 -ar 44100 -i hw:0,0,0 -t 60 -acodec mp2 /mnt/sda1/output.mp3 > /dev/null 2>&1

It worked like a charm thanks. Thanks for the help.

I have to figure out one problem before I declare success. If I use a cheap 3.5 mm microphone (passive one), the audio is muffled. If I use a microphone like this one, the microphone heats up and there is a lot of static noise/white noise build up

I managed to fix the audio quality. It was a combination of gain adjustment + microphone adjustment. I tried 3 different types of USB audio cards. It works with only a certain type of USB audio card -- Creative Soundblaster SB1290. Thanks for your help. The idea of the USB audio card never occurred to me

Plan D:

Re: High-fidelity microphone

I am using this microphone:

https://learn.adafruit.com/adafruit-agc-electret-microphone-amplifier-max9814/overview

The microphone has been performing well. The USB Audio Card is a bit touch and go in terms of its performance

Hi,

I'm trying with this and first errors appeared.

I'm using Arduino Yun & a cheap USB Sound card. And for the moment a microphon plug directly to the USB Sound Card. After installing everything with the opkg command I send this command as you wrote it:

ffmpeg -y -f alsa -acodec pcm_s16le -ac 1 -ar 44100 -i hw:0,0,0 -t 60 -acodec mp2 /mnt/sda1/output.mp3

It didn't work. What I receive are two errors:

  1. [mp3 @ 0xbd24f0] Invalid audio stream. Exactly one MP3 audio stream is required.

  2. Could not write header for output file #0 (incorrect codec parameters ?)

Any help will be appreciated

Thanks

Complete output:

root@Arduino:~# ffmpeg -y -f alsa -acodec pcm_s16le -ac 1 -ar 44100 -i hw:0,0,0 -t 60 -acodec mp2 /mnt/sda1/output.mp3 ffmpeg version 0.11.2 Copyright (c) 2000-2012 the FFmpeg developers built on Sep 12 2013 15:56:28 with gcc 4.6.4 20121210 (prerelease) configuration: --enable-cross-compile --cross-prefix=mips-openwrt-linux-uclibc- --arch=mips --target-os=linux --prefix=/usr --enable-shared --enable-static --disable-debug --pkg-config=pkg-config --enable-gpl --enable-version3 --disable-asm --disable-doc --disable-dxva2 --enable-pthreads --disable-optimizations --enable-small --disable-stripping --enable-zlib --disable-outdevs libavutil 51. 54.100 / 51. 54.100 libavcodec 54. 23.100 / 54. 23.100 libavformat 54. 6.100 / 54. 6.100 libavdevice 54. 0.100 / 54. 0.100 libavfilter 2. 77.100 / 2. 77.100 libswscale 2. 1.100 / 2. 1.100 libswresample 0. 15.100 / 0. 15.100 libpostproc 52. 0.100 / 52. 0.100 [alsa @ 0xbcb620] Estimating duration from bitrate, this may be inaccurate Guessed Channel Layout for Input Stream #0.0 : mono Input #0, alsa, from 'hw:0,0,0': Duration: N/A, start: 1436128640.333616, bitrate: 512 kb/s Stream #0:0: Audio: pcm_s16le, 32000 Hz, mono, s16, 512 kb/s [mp3 @ 0xbd24f0] Invalid audio stream. Exactly one MP3 audio stream is required. Output #0, mp3, to '/mnt/sda1/output.mp3': Metadata: encoder : Lavf54.6.100 Stream #0:0: Audio: mp2, 32000 Hz, mono, s16, 128 kb/s Stream mapping: Stream #0:0 -> #0:0 (pcm_s16le -> mp2) Could not write header for output file #0 (incorrect codec parameters ?)

The output of “arecord -l”

arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Set [C-Media USB Headphone Set], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Make sure has powered USB Hub.