Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SD compability #32

Closed
killamorri07 opened this issue Dec 6, 2022 · 4 comments
Closed

SD compability #32

killamorri07 opened this issue Dec 6, 2022 · 4 comments

Comments

@killamorri07
Copy link

Hi, I'm using Arduino Due.
My goal is to write and save an audio with 8bit and sr = 16kHz to sd card. I'm using SdFat32. I have test run all component by itself however when I tried to combine SdFat32 and modify the code from your example, I can not initiate SdFat32 at all. It always gave me an error(can not find SdFat32).

Thank you in advance. I really looking forward to hear from you.

@TMRh20
Copy link
Owner

TMRh20 commented Dec 6, 2022

What is the exact error message you are getting?
Also can you post some example code that demonstrates the issue?

@killamorri07
Copy link
Author

I have not written my own code, I just change the SD.h part to SdFat and file to file32.

`/******** User Config ************************************/

#define sd_CS_PIN 4
#define AUDIO_DEBUG
#define RECORD_DEBUG

const char newWavFile[] = "test.wav";

//
#include <SPI.h>
#include <SdFat.h>
#include <sdios.h>
#include <AutoAnalogAudio.h>
/
/
AutoAnalog aaAudio;
SdFat32 sd;
File32 myFile;
File32 recFile;
//
#include "myWAV.h"
#include "myRecording.h"
/
/

void setup() {

Serial.begin(115200);

if (!sd.begin(sd_CS_PIN)) {
Serial.println("sd init failed!");
return;
}
Serial.println("sd ok\nAnalog Audio Begin");

aaAudio.begin(1, 1); // Start AAAudio with ADC & DAC
aaAudio.autoAdjust = 0; // Disable automatic timer adjustment

}

/*********************************************************/
uint32_t displayTimer = 0;

void loop() {

if (millis() - displayTimer > 1000) {
displayTimer = millis();
if (counter) {
Serial.print("Samples per Second: ");
Serial.println(counter * MAX_BUFFER_SIZE);
}
counter = 0;
}

if (Serial.available()) {
char input = Serial.read();
switch (input) {

  case '1':  playAudio("M8b24kM.wav");  break; //Play a *.wav file by name - 8bit, 24khz, Mono
  case '2':  playAudio("M8b24kS.wav");  break; //Play  8bit, 24khz, Stereo
  case '3':  playAudio("M16b24kS.wav"); break; //Play 16bit, 24khz, Stereo
  case '4':  playAudio("M8b44kST.wav"); break; //Play  8bit, 44khz, Stereo
  case '5':  channelSelection = 0;      break; //Play the audio on DAC0
  case '6':  channelSelection = 1;      break; //Play the audio on DAC1
  case '7':  channelSelection = 2;      break; //Play the audio on DAC0 & DAC1
  case '8':  Serial.println("OK");      break;
  case '9':  startRecording(newWavFile, 11000); break; //Start recording @11khz,8-bit,Mono
  case '0':  stopRecording(newWavFile, 11000);  break; //Stop the recording and finalize the file
  case 'p':  playAudio(newWavFile);      break; //Play back the recorded audio
  case 'D':  sd.remove(newWavFile);      break; //Delete the file and start fresh
}

}
}
this is the main code then this is for the myWav
uint8_t channelSelection = 0;

void loadBuffer();

/*********************************************************/

void DACC_Handler(void) {
aaAudio.feedDAC(channelSelection); //Feed the DAC with the data loaded into the dacBuffer
aaAudio.dacHandler(); //Link the DAC ISR/IRQ to the library. Called by the MCU when DAC is ready for data
loadBuffer();
}

/********************************************************/
/
Function to open the audio file, seek to starting position and enable the DAC */

void playAudio(const char *audioFile) {

uint32_t sampleRate = 16000;
uint16_t numChannels = 1;
uint16_t bitsPerSample = 8;
uint32_t dataSize = 0;
uint32_t startPosition = 44;

if (recFile) {
aaAudio.adcInterrupts(false);
recFile.close();
}

if (myFile) {
aaAudio.disableDAC();
myFile.close();
//delay(25);
}

//Open the designated file
myFile = sd.open(audioFile);

if (myFile) {
myFile.seek(22);
myFile.read((byte*)&numChannels, 2);
myFile.read((byte*)&sampleRate, 4);
myFile.seek(34);
myFile.read((byte*)&bitsPerSample, 2);
myFile.seek(40);
myFile.read((byte*)&dataSize, 4);
dataSize += 44; //Set this variable to the total size of header + data

#if defined (AUDIO_DEBUG)
Serial.print("\nNow Playing ");
Serial.println(audioFile);
Serial.print("Channels ");
Serial.print(numChannels);
Serial.print(", SampleRate ");
Serial.print(sampleRate);
Serial.print(", BitsPerSample ");
Serial.println(bitsPerSample);
#endif

if (myFile.size() > dataSize) {
  startPosition = myFile.size() - dataSize;

#if defined (AUDIO_DEBUG)
Serial.println("Skipping metadata");
#endif
}

if (bitsPerSample > 10 ) {
  bitsPerSample = 12;
} else if (bitsPerSample > 8) {
  bitsPerSample = 10;
} else {
  bitsPerSample = 8;
}

sampleRate *= numChannels;
aaAudio.dacBitsPerSample = bitsPerSample;
aaAudio.setSampleRate(sampleRate);

#if defined (AUDIO_DEBUG)
Serial.print("Timer Rate ");
Serial.print(sampleRate);
Serial.print(", DAC Bits Per Sample ");
Serial.println(bitsPerSample);
#endif

//Skip past the WAV header
myFile.seek(startPosition);
//Load one buffer
loadBuffer();
//Feed the DAC to start playback
aaAudio.feedDAC();

} else {
#if defined (AUDIO_DEBUG)
Serial.print("Failed to open ");
Serial.println(audioFile);
#endif
}
}

/********************************************************/
/
Function called from DAC interrupt after dacHandler(). Loads data into the dacBuffer */

void loadBuffer() {

if (myFile) {
if (myFile.available()) {
if (aaAudio.dacBitsPerSample == 8) {
//Load 32 samples into the 8-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer, MAX_BUFFER_SIZE);
} else {
//Load 32 samples (64 bytes) into the 16-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer16, MAX_BUFFER_SIZE * 2);
//Convert the 16-bit samples to 12-bit
for (int i = 0; i < MAX_BUFFER_SIZE; i++) {
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
}
}
} else {
#if defined (AUDIO_DEBUG)
Serial.println("File close");
#endif
myFile.close();
aaAudio.disableDAC();
}
}
}

and myRecording

/*********************************************************/

/* WAV HEADER STRUCTURE */
struct wavStruct {
const char chunkID[4] = {'R', 'I', 'F', 'F'};
uint32_t chunkSize = 36; //Size of (entire file in bytes - 8 bytes) or (data size + 36)
const char format[4] = {'W', 'A', 'V', 'E'};
const char subchunkID[4] = {'f', 'm', 't', ' '};
const uint32_t subchunkSize = 16;
const uint16_t audioFormat = 1; //PCM == 1
uint16_t numChannels = 1; //1=Mono, 2=Stereo
uint32_t sampleRate = 11000;
uint32_t byteRate = 11000; //== SampleRate * NumChannels * BitsPerSample/8
uint16_t blockAlign = 1; //== NumChannels * BitsPerSample/8
uint16_t bitsPerSample = 8; //8,16,32...
const char subChunk2ID[4] = {'d', 'a', 't', 'a'};
uint32_t subChunk2Size = 0; //== NumSamples * NumChannels * BitsPerSample/8
//Data //The audio data
};

//
uint32_t counter = 0;
/
/

void ADC_Handler(void) { //ADC Interrupt triggered by ADC sampling completion
aaAudio.getADC();
if (recFile) {
recFile.write(aaAudio.adcBuffer, MAX_BUFFER_SIZE); //Write the data to sd as it is available
counter++;
}
}

/*********************************************************/

void startRecording(const char *fileName, uint32_t sampleRate) {

#if defined (RECORD_DEBUG)
Serial.print("Start Recording: ");
Serial.println(fileName);
#endif

if (recFile) {
aaAudio.adcInterrupts(false);
recFile.close();
}
if (myFile) { //Close any open playback files & disable the DAC
aaAudio.disableDAC();
myFile.close();
}
recFile = sd.open(fileName, FILE_WRITE); //Open the file for writing

if (!recFile) {
#if defined (RECORD_DEBUG)
Serial.println("Failed to open file");
#endif
return;
}
recFile.seek(0); //Write a blank WAV header
uint8_t bb = 0;
for (int i = 0; i < 44; i++) {
recFile.write(bb);
}

aaAudio.adcBitsPerSample = 8; //Configure AAAudio
aaAudio.setSampleRate(sampleRate);

aaAudio.getADC();
aaAudio.getADC();
aaAudio.adcInterrupts(true);

}

/*********************************************************/

void createWavHeader(const char *fileName, uint32_t sampleRate ) {

if (!sd.exists(fileName)) {
#if defined (RECORD_DEBUG)
Serial.println("File does not exist, please write WAV/PCM data starting at byte 44");
#endif
return;
}
recFile = sd.open(fileName, FILE_WRITE);

if (recFile.size() <= 44) {
#if defined (RECORD_DEBUG)
Serial.println("File contains no data, exiting");
#endif
recFile.close();
return;
}

wavStruct wavHeader;
wavHeader.chunkSize = recFile.size() - 8;
//wavHeader.numChannels = numChannels;
wavHeader.sampleRate = sampleRate;
wavHeader.byteRate = sampleRate * wavHeader.numChannels * wavHeader.bitsPerSample / 8;
wavHeader.blockAlign = wavHeader.numChannels * wavHeader.bitsPerSample / 8;
//wavHeader.bitsPerSample = bitsPerSample;
wavHeader.subChunk2Size = recFile.size() - 44;

#if defined (RECORD_DEBUG)
Serial.print("WAV Header Write ");
#endif

recFile.seek(0);
if ( recFile.write((byte*)&wavHeader, 44) > 0) {
#if defined (RECORD_DEBUG)
Serial.println("OK");
} else {
Serial.println("Failed");
#endif
}
recFile.close();

}

/*********************************************************/

void stopRecording(const char *fileName, uint32_t sampleRate) {

aaAudio.adcInterrupts(false); //Disable the ADC interrupt
recFile.close(); //Close the file
createWavHeader(fileName, sampleRate); //Add appropriate header info, to make it a valid *.wav file
#if defined (RECORD_DEBUG)
Serial.println("Recording Stopped");
#endif
}
`

I am not sure is it because I did not have #define SPI_CLOCK SD_SCK_MHZ(21) or I just simpliy misunderstood your code.
image

@TMRh20
Copy link
Owner

TMRh20 commented Dec 7, 2022

Yeah, according to my notes with SDFat on the Due you need to configure the SPI frequency down to 10Mhz. I think you can call if !SD.begin(SD_CS_PIN,SPI_DIV6_SPEED); or something like that, but I can't remember exactly how I did it.

@killamorri07
Copy link
Author

okay, I will try... thank you :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants