The simple wave recorder and player project is a audio mini-project.
Dependencies: SDHCFileSystem FatFileSystem mbed wavfile
main.cpp
- Committer:
- shintamainjp
- Date:
- 2012-04-14
- Revision:
- 0:1a515b688b8c
File content as of revision 0:1a515b688b8c:
/* * =============================================================== * 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; }