From a2be6ab930b69cff1bd63b568a147d486b1c2a70 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Feb 2023 14:24:16 +0100 Subject: [PATCH 01/15] Adding audio_playback as provided by FT content. --- .../audio_playback/audio_playback.ino | 68 +++++ .../Beginner/audio_playback/wav_seeker.cpp | 233 ++++++++++++++++++ examples/Beginner/audio_playback/wav_seeker.h | 6 + 3 files changed, 307 insertions(+) create mode 100644 examples/Beginner/audio_playback/audio_playback.ino create mode 100644 examples/Beginner/audio_playback/wav_seeker.cpp create mode 100644 examples/Beginner/audio_playback/wav_seeker.h diff --git a/examples/Beginner/audio_playback/audio_playback.ino b/examples/Beginner/audio_playback/audio_playback.ino new file mode 100644 index 0000000..41ad68e --- /dev/null +++ b/examples/Beginner/audio_playback/audio_playback.ino @@ -0,0 +1,68 @@ +/* + * GIGA R1 - Audio Playback + * Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive. +*/ + +#include +#include +#include + +// AdvancedDAC library is included inside wav_seeker library +#include "wav_seeker.h" +AdvancedDAC dac1(A12); + +USBHostMSD msd; +mbed::FATFileSystem usb("USB_DRIVE_NAME"); + +void setup() { + Serial.begin(115200); + while (!Serial); + + pinMode(PA_15, OUTPUT); + digitalWrite(PA_15, HIGH); + + delay(2500); + Serial.println("Starting USB File Read example..."); + + while (!msd.connect()) { + delay(1000); + } + + Serial.println("Mounting USB device..."); + int err = usb.mount(&msd); + if (err) { + Serial.print("Error mounting USB device "); + Serial.println(err); + while (1); + } + + // Read + Serial.print("read done "); + mbed::fs_file_t file; + struct dirent *ent; + int dirIndex = 0; + int res = 0; + Serial.println("Open file.."); + + // 16-bit PCM Mono 16kHz realigned noise reduction + FILE *f = fopen("/USB_DRIVE_NAME/AUDIO_SAMPLE.wav", "r+"); + + // Crucial (from mBed) + wav_play_rl(f, dac1, false); + + // Close the file + Serial.println("File closing"); + fflush(stdout); + err = fclose(f); + if (err < 0) { + Serial.print("fclose error: "); + Serial.print(strerror(errno)); + Serial.print(" ("); + Serial.print(-errno); + Serial.print(")"); + } else { + Serial.println("File closed!"); + } +} + +void loop() {} \ No newline at end of file diff --git a/examples/Beginner/audio_playback/wav_seeker.cpp b/examples/Beginner/audio_playback/wav_seeker.cpp new file mode 100644 index 0000000..cc1355c --- /dev/null +++ b/examples/Beginner/audio_playback/wav_seeker.cpp @@ -0,0 +1,233 @@ +/* + * Based on mBed's repo, algorithm based of the wave_player library by Steve Ravet + * https://os.mbed.com/users/sparkfun/code/wave_player/ + * Adapted to GIGA R1 +*/ + +#include "wav_seeker.h" + +unsigned short DAC_fifo[256]; +short DAC_wptr; +volatile short DAC_rptr; +short DAC_on; + +typedef struct uFMT_STRUCT { + short comp_code; + short num_channels; + unsigned sample_rate; + unsigned avg_Bps; + short block_align; + short sig_bps; +} FMT_STRUCT; + +void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ + unsigned chunk_id,chunk_size,channel; + unsigned data,samp_int,i; + short unsigned dac_data; + long long slice_value; + char *slice_buf; + short *data_sptr; + unsigned char *data_bptr; + int *data_wptr; + FMT_STRUCT wav_format; + long slice,num_slices; + DAC_wptr=0; + DAC_rptr=0; + + for (i=0;i<256;i+=2) { + DAC_fifo[i]=0; + DAC_fifo[i+1]=3000; + } + + DAC_wptr=4; + DAC_on=0; + + fread(&chunk_id,4,1,wavefile); + fread(&chunk_size,4,1,wavefile); + + while (!feof(wavefile)) { + if (verbosity) + Serial.print(F("Read chunk ID =")); + Serial.println(chunk_id); + Serial.print(F("Read chunk size =")); + Serial.println(chunk_size); + + switch (chunk_id) { + case 0x46464952: + fread(&data,4,1,wavefile); + if (verbosity) { + Serial.println(F("RIFF chunk")); + Serial.print(F(" chunk size = ")); + Serial.println(chunk_size); + Serial.print(F(" RIFF type = ")); + Serial.println(data); + } + break; + case 0x20746d66: + fread(&wav_format,sizeof(wav_format),1,wavefile); + if (verbosity) { + Serial.println(F("FORMAT chunk")); + Serial.print(F(" chunk size = ")); + Serial.println(chunk_size); + Serial.print(F(" compression code =")); + Serial.println(wav_format.comp_code); + Serial.print(F(" channels =")); + Serial.println(wav_format.num_channels); + Serial.print(F(" samples/sec =")); + Serial.println(wav_format.sample_rate); + Serial.print(F(" bytes/sec =")); + Serial.println(wav_format.avg_Bps); + Serial.print(F(" block align =")); + Serial.println(wav_format.block_align); + Serial.print(F(" bits per sample =")); + Serial.println(wav_format.sig_bps); + } + + // Initializing AdvancedAnalogRedux + + if (!dac_out.begin(AN_RESOLUTION_12, wav_format.sample_rate, 256, 512)) { + Serial.println("Failed to start DAC1 !"); + while (1); + } else{ + Serial.println(F("DAC1 Initialized")); + } + + if (chunk_size > sizeof(wav_format)) + fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR); + break; + case 0x61746164: + slice_buf=(char *)malloc(wav_format.block_align); + if (!slice_buf) { + Serial.println(F("Unable to malloc slice buffer")); + exit(1); + } + num_slices=chunk_size/wav_format.block_align; + samp_int=1000000/(wav_format.sample_rate); + + if (verbosity) { + Serial.println(F("DATA chunk")); + Serial.print(F(" chunk size =")); + Serial.println(chunk_size); + Serial.print(F(" slices =")); + Serial.println(num_slices); + Serial.print(F(" Ideal sample interval= ")); + Serial.println((unsigned)(1000000.0/wav_format.sample_rate)); + Serial.print(F(" programmed interrupt tick interval =")); + Serial.println(samp_int); + } + DAC_on=1; + + for (slice=0;slice>>>>>>>>>>>>>")); + Serial.print(F("sample =")); + Serial.println(slice); + Serial.print(F("wptr =")); + Serial.println(DAC_wptr); + Serial.print(F("slice value =")); + Serial.println((int)slice_value); + Serial.print(F("dac_data =")); + Serial.println(dac_data); + DAC_fifo[DAC_wptr]=dac_data; + + // Custom_mode begin + + DAC_wptr=(DAC_wptr+1) & 0xff; + // Conditional addition to switch between channels - FOR STEREO + if (DAC_wptr >= 255){ + static size_t lut_offs = 0; + + Serial.println(F("Proceeding DAC ...")); + // Get a free buffer for writing. + SampleBuffer buf = dac_out.dequeue(); + // Write data to buffer. + for (size_t i=0; i Date: Mon, 20 Feb 2023 14:26:04 +0100 Subject: [PATCH 02/15] Rename audio_playback to Audio_playback as to be consistent with overall example naming. --- .../audio_playback.ino => Audio_Playback/Audio_Playback.ino} | 0 .../Beginner/{audio_playback => Audio_Playback}/wav_seeker.cpp | 0 examples/Beginner/{audio_playback => Audio_Playback}/wav_seeker.h | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename examples/Beginner/{audio_playback/audio_playback.ino => Audio_Playback/Audio_Playback.ino} (100%) rename examples/Beginner/{audio_playback => Audio_Playback}/wav_seeker.cpp (100%) rename examples/Beginner/{audio_playback => Audio_Playback}/wav_seeker.h (100%) diff --git a/examples/Beginner/audio_playback/audio_playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino similarity index 100% rename from examples/Beginner/audio_playback/audio_playback.ino rename to examples/Beginner/Audio_Playback/Audio_Playback.ino diff --git a/examples/Beginner/audio_playback/wav_seeker.cpp b/examples/Beginner/Audio_Playback/wav_seeker.cpp similarity index 100% rename from examples/Beginner/audio_playback/wav_seeker.cpp rename to examples/Beginner/Audio_Playback/wav_seeker.cpp diff --git a/examples/Beginner/audio_playback/wav_seeker.h b/examples/Beginner/Audio_Playback/wav_seeker.h similarity index 100% rename from examples/Beginner/audio_playback/wav_seeker.h rename to examples/Beginner/Audio_Playback/wav_seeker.h From 0cbe2f0e3c5cd572aeb234413c22737bbbd9ab67 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 24 Feb 2023 10:43:20 +0100 Subject: [PATCH 03/15] CI: Install dependency USBHostMbed5 as dependency. Required for Audio_Playback. --- .github/workflows/compile-examples.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 438602a..e1bb5ff 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -49,6 +49,8 @@ jobs: libraries: | # Install the library from the local path. - source-path: ./ + - source-url: https://github.com/facchinm/USBHostMbed5.git + version: test_hs_in_fs sketch-paths: | - examples enable-deltas-report: true From 4e63368f80ccccc67d089a73b0f5a130ce5bfc72 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 24 Feb 2023 10:53:20 +0100 Subject: [PATCH 04/15] Fix spelling mistakes. --- examples/Beginner/Audio_Playback/wav_seeker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Beginner/Audio_Playback/wav_seeker.cpp b/examples/Beginner/Audio_Playback/wav_seeker.cpp index cc1355c..7301d05 100644 --- a/examples/Beginner/Audio_Playback/wav_seeker.cpp +++ b/examples/Beginner/Audio_Playback/wav_seeker.cpp @@ -159,7 +159,7 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ slice_value/=wav_format.num_channels; switch (wav_format.sig_bps) { - // Working for 8 bit for 12 bit output - acceleartes in the end + // Working for 8 bit for 12 bit output - accelerates in the end case 8: slice_value<<=4; break; // WORKING 12 BIT - SCALING DOWN FROM 16 BIT TO 12 BIT (Applied from 16-Bit wav sample files ) From eee2c295865f4e075591e0141c74abbd177bd1fb Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Fri, 24 Feb 2023 10:53:43 +0100 Subject: [PATCH 05/15] Convert to UNIX file endings. --- .../Beginner/Audio_Playback/wav_seeker.cpp | 464 +++++++++--------- examples/Beginner/Audio_Playback/wav_seeker.h | 10 +- 2 files changed, 237 insertions(+), 237 deletions(-) diff --git a/examples/Beginner/Audio_Playback/wav_seeker.cpp b/examples/Beginner/Audio_Playback/wav_seeker.cpp index 7301d05..ba50a20 100644 --- a/examples/Beginner/Audio_Playback/wav_seeker.cpp +++ b/examples/Beginner/Audio_Playback/wav_seeker.cpp @@ -1,233 +1,233 @@ -/* - * Based on mBed's repo, algorithm based of the wave_player library by Steve Ravet - * https://os.mbed.com/users/sparkfun/code/wave_player/ - * Adapted to GIGA R1 -*/ - -#include "wav_seeker.h" - -unsigned short DAC_fifo[256]; -short DAC_wptr; -volatile short DAC_rptr; -short DAC_on; - -typedef struct uFMT_STRUCT { - short comp_code; - short num_channels; - unsigned sample_rate; - unsigned avg_Bps; - short block_align; - short sig_bps; -} FMT_STRUCT; - -void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ - unsigned chunk_id,chunk_size,channel; - unsigned data,samp_int,i; - short unsigned dac_data; - long long slice_value; - char *slice_buf; - short *data_sptr; - unsigned char *data_bptr; - int *data_wptr; - FMT_STRUCT wav_format; - long slice,num_slices; - DAC_wptr=0; - DAC_rptr=0; - - for (i=0;i<256;i+=2) { - DAC_fifo[i]=0; - DAC_fifo[i+1]=3000; - } - - DAC_wptr=4; - DAC_on=0; - - fread(&chunk_id,4,1,wavefile); - fread(&chunk_size,4,1,wavefile); - - while (!feof(wavefile)) { - if (verbosity) - Serial.print(F("Read chunk ID =")); - Serial.println(chunk_id); - Serial.print(F("Read chunk size =")); - Serial.println(chunk_size); - - switch (chunk_id) { - case 0x46464952: - fread(&data,4,1,wavefile); - if (verbosity) { - Serial.println(F("RIFF chunk")); - Serial.print(F(" chunk size = ")); - Serial.println(chunk_size); - Serial.print(F(" RIFF type = ")); - Serial.println(data); - } - break; - case 0x20746d66: - fread(&wav_format,sizeof(wav_format),1,wavefile); - if (verbosity) { - Serial.println(F("FORMAT chunk")); - Serial.print(F(" chunk size = ")); - Serial.println(chunk_size); - Serial.print(F(" compression code =")); - Serial.println(wav_format.comp_code); - Serial.print(F(" channels =")); - Serial.println(wav_format.num_channels); - Serial.print(F(" samples/sec =")); - Serial.println(wav_format.sample_rate); - Serial.print(F(" bytes/sec =")); - Serial.println(wav_format.avg_Bps); - Serial.print(F(" block align =")); - Serial.println(wav_format.block_align); - Serial.print(F(" bits per sample =")); - Serial.println(wav_format.sig_bps); - } - - // Initializing AdvancedAnalogRedux - - if (!dac_out.begin(AN_RESOLUTION_12, wav_format.sample_rate, 256, 512)) { - Serial.println("Failed to start DAC1 !"); - while (1); - } else{ - Serial.println(F("DAC1 Initialized")); - } - - if (chunk_size > sizeof(wav_format)) - fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR); - break; - case 0x61746164: - slice_buf=(char *)malloc(wav_format.block_align); - if (!slice_buf) { - Serial.println(F("Unable to malloc slice buffer")); - exit(1); - } - num_slices=chunk_size/wav_format.block_align; - samp_int=1000000/(wav_format.sample_rate); - - if (verbosity) { - Serial.println(F("DATA chunk")); - Serial.print(F(" chunk size =")); - Serial.println(chunk_size); - Serial.print(F(" slices =")); - Serial.println(num_slices); - Serial.print(F(" Ideal sample interval= ")); - Serial.println((unsigned)(1000000.0/wav_format.sample_rate)); - Serial.print(F(" programmed interrupt tick interval =")); - Serial.println(samp_int); - } - DAC_on=1; - - for (slice=0;slice>>>>>>>>>>>>>")); - Serial.print(F("sample =")); - Serial.println(slice); - Serial.print(F("wptr =")); - Serial.println(DAC_wptr); - Serial.print(F("slice value =")); - Serial.println((int)slice_value); - Serial.print(F("dac_data =")); - Serial.println(dac_data); - DAC_fifo[DAC_wptr]=dac_data; - - // Custom_mode begin - - DAC_wptr=(DAC_wptr+1) & 0xff; - // Conditional addition to switch between channels - FOR STEREO - if (DAC_wptr >= 255){ - static size_t lut_offs = 0; - - Serial.println(F("Proceeding DAC ...")); - // Get a free buffer for writing. - SampleBuffer buf = dac_out.dequeue(); - // Write data to buffer. - for (size_t i=0; i sizeof(wav_format)) + fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR); + break; + case 0x61746164: + slice_buf=(char *)malloc(wav_format.block_align); + if (!slice_buf) { + Serial.println(F("Unable to malloc slice buffer")); + exit(1); + } + num_slices=chunk_size/wav_format.block_align; + samp_int=1000000/(wav_format.sample_rate); + + if (verbosity) { + Serial.println(F("DATA chunk")); + Serial.print(F(" chunk size =")); + Serial.println(chunk_size); + Serial.print(F(" slices =")); + Serial.println(num_slices); + Serial.print(F(" Ideal sample interval= ")); + Serial.println((unsigned)(1000000.0/wav_format.sample_rate)); + Serial.print(F(" programmed interrupt tick interval =")); + Serial.println(samp_int); + } + DAC_on=1; + + for (slice=0;slice>>>>>>>>>>>>>")); + Serial.print(F("sample =")); + Serial.println(slice); + Serial.print(F("wptr =")); + Serial.println(DAC_wptr); + Serial.print(F("slice value =")); + Serial.println((int)slice_value); + Serial.print(F("dac_data =")); + Serial.println(dac_data); + DAC_fifo[DAC_wptr]=dac_data; + + // Custom_mode begin + + DAC_wptr=(DAC_wptr+1) & 0xff; + // Conditional addition to switch between channels - FOR STEREO + if (DAC_wptr >= 255){ + static size_t lut_offs = 0; + + Serial.println(F("Proceeding DAC ...")); + // Get a free buffer for writing. + SampleBuffer buf = dac_out.dequeue(); + // Write data to buffer. + for (size_t i=0; i Date: Mon, 27 Feb 2023 07:18:23 +0100 Subject: [PATCH 06/15] Cleaning up example file. --- .../Audio_Playback/Audio_Playback.ino | 52 ++++++++----------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index 41ad68e..c1a4c3e 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -1,6 +1,7 @@ /* * GIGA R1 - Audio Playback * Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive. + * In order for this sketch to work you need to rename 'USB_DRIVE_NAME' to the name of your USB stick drive. */ #include @@ -14,55 +15,44 @@ AdvancedDAC dac1(A12); USBHostMSD msd; mbed::FATFileSystem usb("USB_DRIVE_NAME"); -void setup() { +void setup() +{ Serial.begin(115200); while (!Serial); pinMode(PA_15, OUTPUT); digitalWrite(PA_15, HIGH); - delay(2500); - Serial.println("Starting USB File Read example..."); + Serial.println("Please connect a USB stick to the GIGA's USB port ..."); - while (!msd.connect()) { + while (!msd.connect()) delay(1000); - } Serial.println("Mounting USB device..."); - int err = usb.mount(&msd); - if (err) { + int const rc_mount = usb.mount(&msd); + if (rc_mount) + { Serial.print("Error mounting USB device "); - Serial.println(err); - while (1); + Serial.println(rc_mount); + return; } - // Read - Serial.print("read done "); - mbed::fs_file_t file; - struct dirent *ent; - int dirIndex = 0; - int res = 0; - Serial.println("Open file.."); + Serial.println("Opening audio file.."); // 16-bit PCM Mono 16kHz realigned noise reduction - FILE *f = fopen("/USB_DRIVE_NAME/AUDIO_SAMPLE.wav", "r+"); + FILE * f = fopen("/USB_DRIVE_NAME/AUDIO_SAMPLE.wav", "r+"); + if (f == nullptr) + { + Serial.print("Error opening audio file: "); + Serial.println(strerror(errno)); + return; + } // Crucial (from mBed) wav_play_rl(f, dac1, false); - // Close the file - Serial.println("File closing"); - fflush(stdout); - err = fclose(f); - if (err < 0) { - Serial.print("fclose error: "); - Serial.print(strerror(errno)); - Serial.print(" ("); - Serial.print(-errno); - Serial.print(")"); - } else { - Serial.println("File closed!"); - } + // Cleanup. + fclose(f); } -void loop() {} \ No newline at end of file +void loop() {} From eb43c3e8df7cb5941b14f331691fb195672dfb30 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 07:21:11 +0100 Subject: [PATCH 07/15] Cleaning up user output. --- examples/Beginner/Audio_Playback/Audio_Playback.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index c1a4c3e..2efc687 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -28,7 +28,7 @@ void setup() while (!msd.connect()) delay(1000); - Serial.println("Mounting USB device..."); + Serial.println("Mounting USB device ..."); int const rc_mount = usb.mount(&msd); if (rc_mount) { @@ -37,7 +37,7 @@ void setup() return; } - Serial.println("Opening audio file.."); + Serial.println("Opening audio file ..."); // 16-bit PCM Mono 16kHz realigned noise reduction FILE * f = fopen("/USB_DRIVE_NAME/AUDIO_SAMPLE.wav", "r+"); @@ -48,10 +48,10 @@ void setup() return; } - // Crucial (from mBed) + Serial.println("Playing audio file ..."); wav_play_rl(f, dac1, false); - // Cleanup. + Serial.println("Cleaning up ..."); fclose(f); } From c71b511e6969023e0677079d924f5281390f9a79 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 07:23:03 +0100 Subject: [PATCH 08/15] USB_DRIVE_NAME is too long to be accepted as a FAT USB drive name, use USB_DRIVE instead. --- examples/Beginner/Audio_Playback/Audio_Playback.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index 2efc687..3da30e3 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -1,7 +1,7 @@ /* * GIGA R1 - Audio Playback * Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive. - * In order for this sketch to work you need to rename 'USB_DRIVE_NAME' to the name of your USB stick drive. + * In order for this sketch to work you need to rename 'USB_DRIVE' to the name of your USB stick drive. */ #include @@ -13,7 +13,7 @@ AdvancedDAC dac1(A12); USBHostMSD msd; -mbed::FATFileSystem usb("USB_DRIVE_NAME"); +mbed::FATFileSystem usb("USB_DRIVE"); void setup() { @@ -29,7 +29,7 @@ void setup() delay(1000); Serial.println("Mounting USB device ..."); - int const rc_mount = usb.mount(&msd); + int const rc_mount = usb.mount(&msd); if (rc_mount) { Serial.print("Error mounting USB device "); @@ -40,7 +40,7 @@ void setup() Serial.println("Opening audio file ..."); // 16-bit PCM Mono 16kHz realigned noise reduction - FILE * f = fopen("/USB_DRIVE_NAME/AUDIO_SAMPLE.wav", "r+"); + FILE * f = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "r+"); if (f == nullptr) { Serial.print("Error opening audio file: "); From 1b12257ff064186aa1e198b274308dd78f29520d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 13:38:46 +0100 Subject: [PATCH 09/15] Adding AUDIO_SAMPLE.wav via GIT LFS. --- .gitattributes | 1 + examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 .gitattributes create mode 100644 examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d899f65 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.wav filter=lfs diff=lfs merge=lfs -text diff --git a/examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav b/examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav new file mode 100644 index 0000000..0e956d9 --- /dev/null +++ b/examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c17298498cf2a99c95f8dcf246691be4852eaddf8da24268b62854e0056c796 +size 1426086 From bdbc4f8c92c8c95148b6ce94ad03216e41da3de5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 13:51:04 +0100 Subject: [PATCH 10/15] Unmount USB stick after completion of playing the sound file. --- examples/Beginner/Audio_Playback/Audio_Playback.ino | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index 3da30e3..f22fb93 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -53,6 +53,13 @@ void setup() Serial.println("Cleaning up ..."); fclose(f); + int const rc_umount = usb.unmount(); + if (rc_umount < 0) + { + Serial.print("Error unmounting USB drive: "); + Serial.println(rc_umount); + return; + } } void loop() {} From ec320400f018023e75caa42b18aacd36e889731c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 14:01:36 +0100 Subject: [PATCH 11/15] Using the right top-level include: Arduino_AdvancedAnalog. --- .../Audio_Playback/Audio_Playback.ino | 3 +- .../Beginner/Audio_Playback/wav_seeker.cpp | 41 ++++++++++++------- examples/Beginner/Audio_Playback/wav_seeker.h | 6 +-- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index f22fb93..11ff6a7 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -4,8 +4,9 @@ * In order for this sketch to work you need to rename 'USB_DRIVE' to the name of your USB stick drive. */ -#include +#include #include +#include #include // AdvancedDAC library is included inside wav_seeker library diff --git a/examples/Beginner/Audio_Playback/wav_seeker.cpp b/examples/Beginner/Audio_Playback/wav_seeker.cpp index ba50a20..264866b 100644 --- a/examples/Beginner/Audio_Playback/wav_seeker.cpp +++ b/examples/Beginner/Audio_Playback/wav_seeker.cpp @@ -20,7 +20,8 @@ typedef struct uFMT_STRUCT { short sig_bps; } FMT_STRUCT; -void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ +void wav_play_rl(FILE * wavefile, AdvancedDAC & dac_out, bool const verbosity) +{ unsigned chunk_id,chunk_size,channel; unsigned data,samp_int,i; short unsigned dac_data; @@ -46,11 +47,12 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ fread(&chunk_size,4,1,wavefile); while (!feof(wavefile)) { - if (verbosity) + if (verbosity) { Serial.print(F("Read chunk ID =")); Serial.println(chunk_id); Serial.print(F("Read chunk size =")); Serial.println(chunk_size); + } switch (chunk_id) { case 0x46464952: @@ -131,27 +133,30 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ for (channel=0;channel>>>>>>>>>>>>>")); Serial.print(F("sample =")); Serial.println(slice); @@ -181,6 +186,7 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ Serial.println((int)slice_value); Serial.print(F("dac_data =")); Serial.println(dac_data); + } DAC_fifo[DAC_wptr]=dac_data; // Custom_mode begin @@ -189,8 +195,8 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ // Conditional addition to switch between channels - FOR STEREO if (DAC_wptr >= 255){ static size_t lut_offs = 0; - - Serial.println(F("Proceeding DAC ...")); + if (verbosity) + Serial.println(F("Proceeding DAC ...")); // Get a free buffer for writing. SampleBuffer buf = dac_out.dequeue(); // Write data to buffer. @@ -199,12 +205,14 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ } // Writethe buffer to DAC. - Serial.println(F("Writing to DAC ...")); + if (verbosity) + Serial.println(F("Writing to DAC ...")); dac_out.write(buf); DAC_wptr = 0; } else { - Serial.println(F("Slicing")); + if(verbosity) + Serial.println(F("Slicing")); } // Custom_mode end } @@ -213,16 +221,19 @@ void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity){ free(slice_buf); break; case 0x5453494c: - if (verbosity) + if (verbosity) { Serial.print(F("INFO chunk, size")); Serial.println(chunk_size); + } fseek(wavefile,chunk_size,SEEK_CUR); break; default: - Serial.print(F("unknown chunk type =")); - Serial.println(chunk_id); - Serial.print(F("chunk size =")); - Serial.println(chunk_size); + if (verbosity) { + Serial.print(F("unknown chunk type =")); + Serial.println(chunk_id); + Serial.print(F("chunk size =")); + Serial.println(chunk_size); + } data=fseek(wavefile,chunk_size,SEEK_CUR); break; } diff --git a/examples/Beginner/Audio_Playback/wav_seeker.h b/examples/Beginner/Audio_Playback/wav_seeker.h index 4bea3a5..a9011c2 100644 --- a/examples/Beginner/Audio_Playback/wav_seeker.h +++ b/examples/Beginner/Audio_Playback/wav_seeker.h @@ -1,6 +1,6 @@ -#include "AdvancedDAC.h" +#include -struct adc_descr_t; +#include -void wav_play_rl(FILE *wavefile, AdvancedDAC &dac_out, bool verbosity); \ No newline at end of file +void wav_play_rl(FILE * wavefile, AdvancedDAC & dac_out, bool const verbosity); From dad521a57b9e55c46700d65c78531a64e67b6de4 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 14:03:21 +0100 Subject: [PATCH 12/15] Add missing multiple-inclusion guards. --- src/AdvancedADC.h | 5 +++++ src/AdvancedDAC.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/AdvancedADC.h b/src/AdvancedADC.h index 044a2ac..647250b 100644 --- a/src/AdvancedADC.h +++ b/src/AdvancedADC.h @@ -21,6 +21,9 @@ #include "DMABuffer.h" #include "AdvancedAnalog.h" +#ifndef ARDUINO_ADVANCED_ADC_H_ +#define ARDUINO_ADVANCED_ADC_H_ + struct adc_descr_t; class AdvancedADC { @@ -45,3 +48,5 @@ class AdvancedADC { int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers); int stop(); }; + +#endif /* ARDUINO_ADVANCED_ADC_H_ */ diff --git a/src/AdvancedDAC.h b/src/AdvancedDAC.h index 679e292..57707ee 100644 --- a/src/AdvancedDAC.h +++ b/src/AdvancedDAC.h @@ -21,6 +21,9 @@ #include "DMABuffer.h" #include "AdvancedAnalog.h" +#ifndef ARDUINO_ADVANCED_DAC_H_ +#define ARDUINO_ADVANCED_DAC_H_ + struct dac_descr_t; class AdvancedDAC { @@ -47,3 +50,5 @@ class AdvancedDAC { int begin(uint32_t resolution, uint32_t frequency, size_t n_samples=0, size_t n_buffers=0); int stop(); }; + +#endif /* ARDUINO_ADVANCED_DAC_H_ */ From 17715d6c2f481a918ec700b88ddca6ee6000655b Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 14:09:31 +0100 Subject: [PATCH 13/15] No need to open for reading plus more (only read suffices). --- examples/Beginner/Audio_Playback/Audio_Playback.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index 11ff6a7..32c662c 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -9,8 +9,8 @@ #include #include -// AdvancedDAC library is included inside wav_seeker library #include "wav_seeker.h" + AdvancedDAC dac1(A12); USBHostMSD msd; @@ -41,7 +41,7 @@ void setup() Serial.println("Opening audio file ..."); // 16-bit PCM Mono 16kHz realigned noise reduction - FILE * f = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "r+"); + FILE * f = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "r"); if (f == nullptr) { Serial.print("Error opening audio file: "); From 445ef18fa49830b8fc75cb9406875761a207630d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 27 Feb 2023 14:20:13 +0100 Subject: [PATCH 14/15] Adding comment and reducing wait time. --- examples/Beginner/Audio_Playback/Audio_Playback.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index 32c662c..7a0ffac 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -21,13 +21,12 @@ void setup() Serial.begin(115200); while (!Serial); + /* Enable power for HOST USB connector. */ pinMode(PA_15, OUTPUT); digitalWrite(PA_15, HIGH); Serial.println("Please connect a USB stick to the GIGA's USB port ..."); - - while (!msd.connect()) - delay(1000); + while (!msd.connect()) delay(100); Serial.println("Mounting USB device ..."); int const rc_mount = usb.mount(&msd); From 0d1e455e60969ea13e76b3f19ffacff80bcdb188 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Tue, 28 Feb 2023 04:39:23 +0100 Subject: [PATCH 15/15] Fixing example: this works now. --- .../Audio_Playback/Audio_Playback.ino | 124 +++++++-- .../Beginner/Audio_Playback/wav_seeker.cpp | 244 ------------------ examples/Beginner/Audio_Playback/wav_seeker.h | 6 - 3 files changed, 108 insertions(+), 266 deletions(-) delete mode 100644 examples/Beginner/Audio_Playback/wav_seeker.cpp delete mode 100644 examples/Beginner/Audio_Playback/wav_seeker.h diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino index 7a0ffac..a860e43 100644 --- a/examples/Beginner/Audio_Playback/Audio_Playback.ino +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -2,6 +2,7 @@ * GIGA R1 - Audio Playback * Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive. * In order for this sketch to work you need to rename 'USB_DRIVE' to the name of your USB stick drive. + * Furthermore you need to store the provided audio file AUDIO_SAMPLE.wav on it. */ #include @@ -9,13 +10,16 @@ #include #include -#include "wav_seeker.h" - AdvancedDAC dac1(A12); USBHostMSD msd; mbed::FATFileSystem usb("USB_DRIVE"); +FILE * file = nullptr; +int sample_size = 0; +int samples_count = 0; + + void setup() { Serial.begin(115200); @@ -38,28 +42,116 @@ void setup() } Serial.println("Opening audio file ..."); - - // 16-bit PCM Mono 16kHz realigned noise reduction - FILE * f = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "r"); - if (f == nullptr) + + /* 16-bit PCM Mono 16kHz realigned noise reduction */ + file = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "rb"); + if (file == nullptr) { Serial.print("Error opening audio file: "); Serial.println(strerror(errno)); return; } - Serial.println("Playing audio file ..."); - wav_play_rl(f, dac1, false); - - Serial.println("Cleaning up ..."); - fclose(f); - int const rc_umount = usb.unmount(); - if (rc_umount < 0) + Serial.println("Reading audio header ..."); + struct wav_header_t { - Serial.print("Error unmounting USB drive: "); - Serial.println(rc_umount); + char chunkID[4]; //"RIFF" = 0x46464952 + unsigned long chunkSize; //28 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + sum(sizeof(chunk.id) + sizeof(chunk.size) + chunk.size) + char format[4]; //"WAVE" = 0x45564157 + char subchunk1ID[4]; //"fmt " = 0x20746D66 + unsigned long subchunk1Size; //16 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + unsigned short audioFormat; + unsigned short numChannels; + unsigned long sampleRate; + unsigned long byteRate; + unsigned short blockAlign; + unsigned short bitsPerSample; + }; + + wav_header_t header; + fread(&header, sizeof(header), 1, file); + + Serial.println("WAV File Header read:"); + char msg[64] = {0}; + snprintf(msg, sizeof(msg), "File Type: %s", header.chunkID); + Serial.println(msg); + snprintf(msg, sizeof(msg), "File Size: %ld", header.chunkSize); + Serial.println(msg); + snprintf(msg, sizeof(msg), "WAV Marker: %s", header.format); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Format Name: %s", header.subchunk1ID); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Format Length: %ld", header.subchunk1Size); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Format Type: %hd", header.audioFormat); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Number of Channels: %hd", header.numChannels); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Sample Rate: %ld", header.sampleRate); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Sample Rate * Bits/Sample * Channels / 8: %ld", header.byteRate); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Bits per Sample * Channels / 8: %hd", header.blockAlign); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Bits per Sample: %hd", header.bitsPerSample); + Serial.println(msg); + + /* Find the data section of the WAV file. */ + struct chunk_t + { + char ID[4]; + unsigned long size; + }; + + chunk_t chunk; + snprintf(msg, sizeof(msg), "id\t" "size"); + Serial.println(msg); + /* Find data chunk. */ + while (true) + { + fread(&chunk, sizeof(chunk), 1, file); + snprintf(msg, sizeof(msg), "%c%c%c%c\t" "%li", chunk.ID[0], chunk.ID[1], chunk.ID[2], chunk.ID[3], chunk.size); + Serial.println(msg); + if (*(unsigned int *) &chunk.ID == 0x61746164) + break; + /* Skip chunk data bytes. */ + fseek(file, chunk.size, SEEK_CUR); + } + + /* Determine number of samples. */ + sample_size = header.bitsPerSample / 8; + samples_count = chunk.size * 8 / header.bitsPerSample; + snprintf(msg, sizeof(msg), "Sample size = %i", sample_size); Serial.println(msg); + snprintf(msg, sizeof(msg), "Samples count = %i", samples_count); Serial.println(msg); + + /* Configure the advanced DAC. */ + if (!dac1.begin(AN_RESOLUTION_12, header.sampleRate, 256, 16)) + { + Serial.println("Failed to start DAC1 !"); return; } } -void loop() {} +void loop() +{ + if (dac1.available() && !feof(file)) + { + /* Read data from file. */ + uint16_t sample_data[256] = {0}; + fread(sample_data, sample_size, 256, file); + + /* Get a free buffer for writing. */ + SampleBuffer buf = dac1.dequeue(); + + /* Write data to buffer. */ + for (size_t i = 0; i < buf.size(); i++) + { + /* Scale down to 12 bit. */ + uint16_t const dac_val = ((static_cast(sample_data[i])+32768)>>4) & 0x0fff; + buf[i] = dac_val; + } + + /* Write the buffer to DAC. */ + dac1.write(buf); + } +} diff --git a/examples/Beginner/Audio_Playback/wav_seeker.cpp b/examples/Beginner/Audio_Playback/wav_seeker.cpp deleted file mode 100644 index 264866b..0000000 --- a/examples/Beginner/Audio_Playback/wav_seeker.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Based on mBed's repo, algorithm based of the wave_player library by Steve Ravet - * https://os.mbed.com/users/sparkfun/code/wave_player/ - * Adapted to GIGA R1 -*/ - -#include "wav_seeker.h" - -unsigned short DAC_fifo[256]; -short DAC_wptr; -volatile short DAC_rptr; -short DAC_on; - -typedef struct uFMT_STRUCT { - short comp_code; - short num_channels; - unsigned sample_rate; - unsigned avg_Bps; - short block_align; - short sig_bps; -} FMT_STRUCT; - -void wav_play_rl(FILE * wavefile, AdvancedDAC & dac_out, bool const verbosity) -{ - unsigned chunk_id,chunk_size,channel; - unsigned data,samp_int,i; - short unsigned dac_data; - long long slice_value; - char *slice_buf; - short *data_sptr; - unsigned char *data_bptr; - int *data_wptr; - FMT_STRUCT wav_format; - long slice,num_slices; - DAC_wptr=0; - DAC_rptr=0; - - for (i=0;i<256;i+=2) { - DAC_fifo[i]=0; - DAC_fifo[i+1]=3000; - } - - DAC_wptr=4; - DAC_on=0; - - fread(&chunk_id,4,1,wavefile); - fread(&chunk_size,4,1,wavefile); - - while (!feof(wavefile)) { - if (verbosity) { - Serial.print(F("Read chunk ID =")); - Serial.println(chunk_id); - Serial.print(F("Read chunk size =")); - Serial.println(chunk_size); - } - - switch (chunk_id) { - case 0x46464952: - fread(&data,4,1,wavefile); - if (verbosity) { - Serial.println(F("RIFF chunk")); - Serial.print(F(" chunk size = ")); - Serial.println(chunk_size); - Serial.print(F(" RIFF type = ")); - Serial.println(data); - } - break; - case 0x20746d66: - fread(&wav_format,sizeof(wav_format),1,wavefile); - if (verbosity) { - Serial.println(F("FORMAT chunk")); - Serial.print(F(" chunk size = ")); - Serial.println(chunk_size); - Serial.print(F(" compression code =")); - Serial.println(wav_format.comp_code); - Serial.print(F(" channels =")); - Serial.println(wav_format.num_channels); - Serial.print(F(" samples/sec =")); - Serial.println(wav_format.sample_rate); - Serial.print(F(" bytes/sec =")); - Serial.println(wav_format.avg_Bps); - Serial.print(F(" block align =")); - Serial.println(wav_format.block_align); - Serial.print(F(" bits per sample =")); - Serial.println(wav_format.sig_bps); - } - - // Initializing AdvancedAnalogRedux - - if (!dac_out.begin(AN_RESOLUTION_12, wav_format.sample_rate, 256, 512)) { - Serial.println("Failed to start DAC1 !"); - while (1); - } else{ - Serial.println(F("DAC1 Initialized")); - } - - if (chunk_size > sizeof(wav_format)) - fseek(wavefile,chunk_size-sizeof(wav_format),SEEK_CUR); - break; - case 0x61746164: - slice_buf=(char *)malloc(wav_format.block_align); - if (!slice_buf) { - Serial.println(F("Unable to malloc slice buffer")); - exit(1); - } - num_slices=chunk_size/wav_format.block_align; - samp_int=1000000/(wav_format.sample_rate); - - if (verbosity) { - Serial.println(F("DATA chunk")); - Serial.print(F(" chunk size =")); - Serial.println(chunk_size); - Serial.print(F(" slices =")); - Serial.println(num_slices); - Serial.print(F(" Ideal sample interval= ")); - Serial.println((unsigned)(1000000.0/wav_format.sample_rate)); - Serial.print(F(" programmed interrupt tick interval =")); - Serial.println(samp_int); - } - DAC_on=1; - - for (slice=0;slice>>>>>>>>>>>>>")); - Serial.print(F("sample =")); - Serial.println(slice); - Serial.print(F("wptr =")); - Serial.println(DAC_wptr); - Serial.print(F("slice value =")); - Serial.println((int)slice_value); - Serial.print(F("dac_data =")); - Serial.println(dac_data); - } - DAC_fifo[DAC_wptr]=dac_data; - - // Custom_mode begin - - DAC_wptr=(DAC_wptr+1) & 0xff; - // Conditional addition to switch between channels - FOR STEREO - if (DAC_wptr >= 255){ - static size_t lut_offs = 0; - if (verbosity) - Serial.println(F("Proceeding DAC ...")); - // Get a free buffer for writing. - SampleBuffer buf = dac_out.dequeue(); - // Write data to buffer. - for (size_t i=0; i - -#include - -void wav_play_rl(FILE * wavefile, AdvancedDAC & dac_out, bool const verbosity);