The simple wave recorder and player project is a audio mini-project.

Dependencies:   SDHCFileSystem FatFileSystem mbed wavfile

Files at this revision

API Documentation at this revision

Comitter:
shintamainjp
Date:
Sat Apr 14 02:25:17 2012 +0000
Commit message:
Initial version.

Changed in this revision

FatFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
SDHCFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
wavfile.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FatFileSystem.lib	Sat Apr 14 02:25:17 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shintamainjp/code/FatFileSystem/#8c55801ce311
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDHCFileSystem.lib	Sat Apr 14 02:25:17 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shintamainjp/code/SDHCFileSystem/#5afeb866dfef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Apr 14 02:25:17 2012 +0000
@@ -0,0 +1,321 @@
+/*
+ * ===============================================================
+ *  A simple wave recorder & player on mbed
+ * ===============================================================
+ * Copyright (c) 2011-2012 Shinichiro Nakamura
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * ===============================================================
+ */
+
+#include "mbed.h"
+#include "SDHCFileSystem.h"
+#include "wavfile.h"
+
+#define RAM_TOTAL   0x1000
+
+AnalogOut dacout(p18);
+AnalogIn adcin(p20);
+DigitalOut led_play_ok(LED1);
+DigitalOut led_rec_ok(LED2);
+
+Timer timer;
+Timer iometer;
+Ticker ticker;
+SDFileSystem sdc(p5, p6, p7, p8, "sdc");
+
+float buffer[RAM_TOTAL];
+int rp = 0;
+int wp = 0;
+int dropout = 0;
+
+#define WAVFILE_ERROR_PRINT(RESULT) \
+    do { \
+        WavFileResult R = RESULT; \
+        if (R != WavFileResultOK) { \
+            char wavfile_error_print_text[BUFSIZ]; \
+            wavfile_result_string(R, wavfile_error_print_text, sizeof(wavfile_error_print_text)); \
+            printf("%s (code=%d)\r\n", wavfile_error_print_text, R); \
+            return 1; \
+        } \
+    } while(0)
+
+void tickdummy(void)
+{
+}
+
+void tickplay(void)
+{
+    /*
+     * Check the play underflow
+     */
+    if (rp != wp) {
+        dacout = buffer[rp];
+        rp = (rp + 1) & (RAM_TOTAL - 1);
+    } else {
+        dropout++;
+    }
+    led_play_ok = !led_play_ok;
+}
+
+void tickrec(void)
+{
+    /*
+     * Check the rec overflow
+     */
+    int np = (wp + 1) & (RAM_TOTAL - 1);
+    if (np != rp) {
+        buffer[wp] = adcin;
+        wp = np;
+    } else {
+        dropout++;
+    }
+    led_rec_ok = !led_rec_ok;
+}
+
+int play(const char *filename)
+{
+    WavFileResult result;
+    wavfile_info_t info;
+    wavfile_data_t data;
+
+    WAVFILE *wf = wavfile_open(filename, WavFileModeRead, &result);
+    WAVFILE_ERROR_PRINT(result);
+    WAVFILE_ERROR_PRINT(wavfile_read_info(wf, &info));
+
+    printf("[PLAY:%s]\r\n", filename);
+    printf("\tWAVFILE_INFO_AUDIO_FORMAT(&info)    = %d\r\n", WAVFILE_INFO_AUDIO_FORMAT(&info));
+    printf("\tWAVFILE_INFO_NUM_CHANNELS(&info)    = %d\r\n", WAVFILE_INFO_NUM_CHANNELS(&info));
+    printf("\tWAVFILE_INFO_SAMPLE_RATE(&info)     = %d\r\n", WAVFILE_INFO_SAMPLE_RATE(&info));
+    printf("\tWAVFILE_INFO_BYTE_RATE(&info)       = %d\r\n", WAVFILE_INFO_BYTE_RATE(&info));
+    printf("\tWAVFILE_INFO_BLOCK_ALIGN(&info)     = %d\r\n", WAVFILE_INFO_BLOCK_ALIGN(&info));
+    printf("\tWAVFILE_INFO_BITS_PER_SAMPLE(&info) = %d\r\n", WAVFILE_INFO_BITS_PER_SAMPLE(&info));
+
+    const int interval_us =  1000000 / WAVFILE_INFO_SAMPLE_RATE(&info);
+
+    rp = 0;
+    wp = 0;
+    dropout = 0;
+    ticker.attach_us(tickplay, interval_us);
+    while (1) {
+        int np = (wp + 1) & (RAM_TOTAL - 1);
+        while (np == rp) {
+            wait_us(1);
+        }
+        WAVFILE_ERROR_PRINT(wavfile_read_data(wf, &data));
+        if (WAVFILE_DATA_IS_END_OF_DATA(&data)) {
+            break;
+        }
+        buffer[wp] = WAVFILE_DATA_CHANNEL_DATA(&data, 0);
+        wp = np;
+    }
+    ticker.detach();
+    dacout = 0.5;
+    led_play_ok = 0;
+    printf("\t-- Play done. (dropout=%d) --\r\n", dropout);
+
+    WAVFILE_ERROR_PRINT(wavfile_close(wf));
+    return 0;
+}
+
+int rec(const char *filename, const int nsec)
+{
+    WavFileResult result;
+    wavfile_info_t info;
+    wavfile_data_t data;
+
+    WAVFILE_INFO_AUDIO_FORMAT(&info)    = 1;
+    WAVFILE_INFO_NUM_CHANNELS(&info)    = 1;
+    WAVFILE_INFO_SAMPLE_RATE(&info)     = 11025;
+    WAVFILE_INFO_BYTE_RATE(&info)       = 22050;
+    WAVFILE_INFO_BLOCK_ALIGN(&info)     = 2;
+    WAVFILE_INFO_BITS_PER_SAMPLE(&info) = 16;
+
+    WAVFILE *wf = wavfile_open(filename, WavFileModeWrite, &result);
+    WAVFILE_ERROR_PRINT(result);
+    WAVFILE_ERROR_PRINT(wavfile_write_info(wf, &info));
+
+    printf("[REC:%s]\r\n", filename);
+    printf("\tWAVFILE_INFO_AUDIO_FORMAT(&info)    = %d\r\n", WAVFILE_INFO_AUDIO_FORMAT(&info));
+    printf("\tWAVFILE_INFO_NUM_CHANNELS(&info)    = %d\r\n", WAVFILE_INFO_NUM_CHANNELS(&info));
+    printf("\tWAVFILE_INFO_SAMPLE_RATE(&info)     = %d\r\n", WAVFILE_INFO_SAMPLE_RATE(&info));
+    printf("\tWAVFILE_INFO_BYTE_RATE(&info)       = %d\r\n", WAVFILE_INFO_BYTE_RATE(&info));
+    printf("\tWAVFILE_INFO_BLOCK_ALIGN(&info)     = %d\r\n", WAVFILE_INFO_BLOCK_ALIGN(&info));
+    printf("\tWAVFILE_INFO_BITS_PER_SAMPLE(&info) = %d\r\n", WAVFILE_INFO_BITS_PER_SAMPLE(&info));
+
+    const int interval_us =  1000000 / WAVFILE_INFO_SAMPLE_RATE(&info);
+    const unsigned int samples_for_nsec = WAVFILE_INFO_SAMPLE_RATE(&info) * nsec;
+
+    rp = 0;
+    wp = 0;
+    dropout = 0;
+    unsigned int count = 0;
+    ticker.attach_us(tickrec, interval_us);
+    WAVFILE_DATA_NUM_CHANNELS(&data) = 1;
+    while (1) {
+        while (rp == wp) {
+            wait_us(1);
+        }
+
+        WAVFILE_DATA_CHANNEL_DATA(&data, 0) = buffer[rp];
+        rp = (rp + 1) & (RAM_TOTAL - 1);
+        WAVFILE_ERROR_PRINT(wavfile_write_data(wf, &data));
+
+        count++;
+        if (count > samples_for_nsec) {
+            break;
+        }
+    }
+    ticker.detach();
+    led_rec_ok = 0;
+    printf("\t-- Rec done. (dropout=%d) --\r\n", dropout);
+
+    WAVFILE_ERROR_PRINT(wavfile_close(wf));
+    return 0;
+}
+
+int perf_read(const char *filename, const int word_size, const int nsec)
+{
+    FILE *fp = fopen(filename, "rb");
+    if (fp == NULL) {
+        printf("File open failed.\r\n");
+        return 1;
+    }
+
+    printf("[Read performance checking...]\r\n");
+
+    unsigned int total_byte_size = 0;
+    int min_us = 0;
+    int max_us = 0;
+    timer.reset();
+    timer.start();
+    while (timer.read() < nsec) {
+        for (int i = 0; i < word_size; i++) {
+            iometer.reset();
+            iometer.start();
+            volatile int c = fgetc(fp);
+            iometer.stop();
+            int iomv = iometer.read_us();
+            if (iomv < min_us) {
+                min_us = iomv;
+            }
+            if (max_us < iomv) {
+                max_us = iomv;
+            }
+            total_byte_size++;
+        }
+    }
+    timer.stop();
+
+    printf("\tfilename(%s), word_size(%d)\r\n", filename, word_size);
+    printf("\ttime(%d[ms]), total_byte_size(%d)\r\n", timer.read_ms(), total_byte_size);
+    printf("\tThroughput=%f[Bytes/Sec]\r\n", (double)total_byte_size / timer.read_ms() * 1000.0);
+    printf("\tmin_us(%d), max_us(%d), average_us(%d)\r\n", min_us, max_us, timer.read_us() / total_byte_size);
+
+    fclose(fp);
+    return 0;
+}
+
+int perf_write(const char *filename, const int word_size, const int nsec)
+{
+    FILE *fp = fopen(filename, "wb");
+    if (fp == NULL) {
+        printf("File open failed.\r\n");
+        return 1;
+    }
+
+    printf("[Write performance checking...]\r\n");
+
+    unsigned int total_byte_size = 0;
+    int min_us = 0;
+    int max_us = 0;
+    timer.reset();
+    timer.start();
+    while (timer.read() < nsec) {
+        for (int i = 0; i < word_size; i++) {
+            volatile int c = 0x55;
+            iometer.reset();
+            iometer.start();
+            fputc(c, fp);
+            iometer.stop();
+            int iomv = iometer.read_us();
+            if (iomv < min_us) {
+                min_us = iomv;
+            }
+            if (max_us < iomv) {
+                max_us = iomv;
+            }
+            total_byte_size++;
+        }
+    }
+    timer.stop();
+
+    printf("\tfilename(%s), word_size(%d)\r\n", filename, word_size);
+    printf("\ttime(%d[ms]), total_byte_size(%d)\r\n", timer.read_ms(), total_byte_size);
+    printf("\tThroughput=%f[Bytes/Sec]\r\n", (double)total_byte_size / timer.read_ms() * 1000.0);
+    printf("\tmin_us(%d), max_us(%d), average_us(%d)\r\n", min_us, max_us, timer.read_us() / total_byte_size);
+
+    fclose(fp);
+    return 0;
+}
+
+int main(void)
+{
+    printf("\r\n\r\n");
+    printf("=======================================================\r\n");
+    printf(" A simple wave recorder & player on mbed               \r\n");
+    printf(" Copyright(C) 2012 Shinichiro Nakamura (CuBeatSystems) \r\n");
+    printf("=======================================================\r\n");
+
+    ticker.attach_us(tickdummy, 100);
+    wait(1);
+    ticker.detach();
+
+    {
+        const char *perf_filename = "/sdc/perf.bin";
+        const int word_size = 2;
+        const int nsec_write = 20;
+        const int nsec_read = 10;
+        perf_write(perf_filename, word_size, nsec_write);
+        perf_read(perf_filename, word_size, nsec_read);
+    }
+
+    {
+        static const char *target_filename = "/sdc/rec-test.wav";
+        while (1) {
+            /*
+             * 30 seconds recording.
+             */
+            if (rec(target_filename, 30) != 0) {
+                break;
+            }
+            /*
+             * Play it!
+             */
+            if (play(target_filename) != 0) {
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Apr 14 02:25:17 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/737756e0b479
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wavfile.lib	Sat Apr 14 02:25:17 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shintamainjp/code/wavfile/#c853ba46d0b9