It shouldn’t be too complicated when using SparkIntervalTimer library to push the samples in a “sort of steady” pace to the two DACs.
Try this one
//SYSTEM_THREAD(ENABLED)
SYSTEM_MODE(MANUAL)
#include "SparkIntervalTimer/SparkIntervalTimer.h"
#include <math.h>
const int MIDPOINT = 2048; // zenter point for DAC
const int MAX_VOL = 1600; // amplitude around (+/-) center point (no more than 2047! to avoid clipping)
const int SAMPLE_PERIODE = 1000000/44100; // µs between samples (44.1kHz)
const int SAMPLES = 50;
uint16_t sine[SAMPLES]; // one periode over 50 samples is aprox. 880Hz
volatile int r = 0; // sample to play on right channel
volatile int l = 25; // sample to play on left channel (slightly offset)
IntervalTimer tPlayer;
void setup() {
pinMode(DAC1, OUTPUT);
pinMode(DAC2, OUTPUT);
for (int i=0; i < SAMPLES; i++)
{ // precalc one periode sine wave
double x = 2.0 * M_PI * i / SAMPLES;
sine[i] = MIDPOINT + MAX_VOL * sin(x);
}
tPlayer.begin(playSample, SAMPLE_PERIODE, uSec);
}
void loop() {
}
void playSample()
{
analogWrite(DAC1, sine[r++]);
analogWrite(DAC2, sine[l++]);
r %= SAMPLES;
l %= SAMPLES;
}
hi
how are you?
i have one wave file with C language.
i would like to play this c type of wave file with DAC on particle.
but i don't know how to do it.
like this
#include "speaker.h"
SYSTEM_THREAD(ENABLED);
/* Configure audio output */
uint16_t bufferSize = 128;
Speaker speaker(bufferSize);
uint16_t audioFrequency = 22050; // Hz
/* Configure signal parameters */
uint16_t amplitude = 2000; // signal goes from 0 to 65535
uint16_t frequency = 1000; // Hz
uint32_t audioSignal = 0; // current value of the audio signal
/* Generate a sawtooth signal into the Speaker buffer.
* A sawtooth goes up until a limit, then goes back to 0.
*/
void generateSawtooth(uint16_t *buffer)
{
uint32_t increment = ((uint32_t) frequency * amplitude) / audioFrequency;
for (uint16_t i = 0; i < bufferSize; i++) {
buffer[i] = audioSignal;
audioSignal += increment;
if (audioSignal > amplitude) {
audioSignal -= amplitude;
}
}
}
/* Particle function to change the volume of the sawtooth signal by
* changing the maximum value.
*/
int changeAmplitude(String arg)
{
long num = arg.toInt();
if (num >= 0 && num < 65535)
{
amplitude = (uint16_t) num;
if (audioSignal > amplitude) {
audioSignal = 0;
}
}
return amplitude;
}
/* Particle function to change the sawtooth frequency */
int changeFrequency(String arg)
{
long num = arg.toInt();
if (num > 0 && num < audioFrequency)
{
frequency = (uint16_t) num;
}
return frequency;
}
/* Set up the speaker */
void setup() {
Particle.function("amp", changeAmplitude);
Particle.function("freq", changeFrequency);
// Write initial data in the audio buffer. Not mandatory, but if you
// don't do this you'll start with 1 buffer of silence.
generateSawtooth(speaker.getBuffer());
// Start the audio output
speaker.begin(audioFrequency);
}
/* Generate more audio data when needed */
void loop() {
// Call ready as often as possible to avoid the speaker playing the same buffer multiple times.
if (speaker.ready()) {
// Write new audio into the buffer returned by getBuffer
generateSawtooth(speaker.getBuffer());
}
}
The example code does fill a buffer with a sawtooth signal on the fly.
Each time the code calls generateSawtooth(speaker.getBuffer()); the signal data will be regenerated and stored in the provided buffer.
Since you are not intending to use the sawtooth signal, you won’t need to call that.
You would only need to provide your wave_data[] once and let it play over and over.
BTW, the speaker object wants the wave signal as 16bit PCM (uint16_t 0…65535) and not 8bit (char 0…255) what your wave_data[] currently is.
Sorry to resurrect an old thread, but what is the example from the speaker library example supposed to sound like? I’ve been having a fair amount of difficulty getting it to work. As of right now, I’m getting a sound similar to “SHHH… Thump Thump.” Can someone confirm that this is correct? I have a larger aspiration to build my own wifi doorbell, but wasn’t a fan of the DFPlayer audio solution.
Going a route without DFPlayer is proving to be more complicated than I expected…
I tried converting my own audio file into the uint16_t format, and after whittling it down quite a bit, I received the same “SHHH… Thump Thump.” that I was getting before. This tells me that either my hardware is wired up incorrectly (I don’t think so), or there’s something wrong with the code (more likely). I’ll keep playing with it, but if anyone is able to offer some assistance, I would appreciate it!
How did you obtain your sound data?
You could try filling buffer with a sine wave and play that - what do you hear then?
How have you wired your setup?
What speaker are you trying to drive?
Have you got an amplifier?
Your symptoms could fit the effect of having a too low impedance speaker straining the DAC beyond its capabilities.
Update:
I have now tested the sample sound provided with the library and it plays some “didum, didum, …” sound when feeding the DAC signal to some earphones - obvioulsy having GND connected too.
The sound data was obtained in the same manner that the library creator used. I used a wav file, converted it to RAW using Audacity, then converted that with your html that was packaged with the library. I was able to finally get the expected sound out of the speaker by continuing to remove data from my sound variable, but I’m not really sure why. This is my setup -
Particle Photon
LM386 amplifier module (unsure of ohm rating)
4 ohm speaker (measured to actually be 3 ohms)
The amp is powered from a 5v usb input to the photon, and the signal is connected to the DAC pin. Really, that’s all my wiring.
I also have an SD card reader wired up to the photon (pins D1-D4), but it’s not being used at the moment. I believe that the issue was a compiler issue, or possibly too low impedance of a speaker. I did encounter several errors when attempting to compile, and was only successfully able to flash the photon once I removed 80% of my original sound data.
About your SD card: When using D1…D4 you are using D1 as SlaveSelect pin? If not, coult it be that you are using soft SPI? That wouldn’t be the best option here.
You could use SPI1 (D2…D4 with a freely configurable SS pin), but that’d still not allow for the maxium speed.
Max speed can be achieved via SPI (A3…A5 with free choice for SS) - unless you really need stereo sound.
My code doesn’t reference the SD card at all at the moment, but yes, D1 is used as the SlaveSelect. I’m still learning how this all works, but I thought I had read that the photon has 2 options for SPI and this was the faster one? I can certainly switch it to the analog inputs if that is the faster option. My only desire is to have the audio play as soon as the switch is triggered. I’m not sure that the choice of SPI will make that huge of a difference for playback timing.
Also, I tried bypassing my amp and hooking the speaker up to the DAC pin directly, and sadly didn’t get any better results than before. If anything I could hear something slightly different in the “SHHH…” part, but it still mostly sounded like static.
Can you post your converted audio data (or send a link to download the file)?
For your wiring: Event if it's something really simple can you still draw up a schematic and post that?
Images are so much easier to grasp and won't be misinterpreted as easily compared to verbal descriptions.