Skip to content

Commit d5d472a

Browse files
committed
something works, but not quite right?
1 parent 8571cdd commit d5d472a

File tree

2 files changed

+82
-35
lines changed

2 files changed

+82
-35
lines changed

examples/loadsample/loadsample.ino

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <Audio.h>
44
#include <TeensyVariablePlayback.h>
55
#include "flashloader.h"
6-
76
#include <Audio.h>
87
#include <Wire.h>
98
#include <SPI.h>
@@ -56,7 +55,7 @@ AudioPlayArrayResmp *voices[2][4] = {
5655
{ &voice1, &voice2, &voice3, &voice4 },
5756
{ &voice5, &voice6, &voice7, &voice8 } };
5857

59-
newdigate::flashloader loader( 16 * 1024);
58+
newdigate::flashloader loader(1024);
6059
const char * fileNames[2][4] = {
6160
{"loop1.raw", "loop3.raw", "loop5.raw", "loop7.raw" },
6261
{"loop2.raw", "loop4.raw", "loop6.raw", "loop8.raw" } };
@@ -71,11 +70,25 @@ const double durationOfOneBeatInMilliseconds = 1000.0 * (60.0 / tempo);
7170
const uint32_t durationOf32BeatsInMilliseconds = durationOfOneBeatInMilliseconds * 32.0;
7271

7372
void setup() {
73+
AudioMemory(64);
7474
Serial.begin(9600);
75-
AudioMemory(32);
75+
76+
//while (!Serial) { delay(100); };
77+
delay(100);
78+
79+
/*
80+
voice1.enableInterpolation(false);
81+
voice2.enableInterpolation(false);
82+
voice3.enableInterpolation(false);
83+
voice4.enableInterpolation(false);
84+
voice5.enableInterpolation(false);
85+
voice6.enableInterpolation(false);
86+
voice7.enableInterpolation(false);
87+
voice8.enableInterpolation(false);
88+
*/
7689

7790
sgtl5000_1.enable();
78-
sgtl5000_1.volume(0.5f, 0.5f);
91+
sgtl5000_1.volume(1, 1);
7992

8093
Serial.print("Initializing SD card...");
8194
while (!SD.begin(BUILTIN_SDCARD)) {
@@ -86,14 +99,18 @@ void setup() {
8699
}
87100

88101
inline void heap_switch() {
102+
//Serial.printf("Heap switch init: currentWriteHeap=%d currentReadHeap=%d !\n", currentWriteHeap, currentReadHeap);
89103
currentWriteHeap ++;
90104
currentWriteHeap %= 2;
91105
currentReadHeap = 1 - currentWriteHeap;
92106
numLoaded = 0;
107+
Serial.printf("Heap switch complete: currentWriteHeap=%d currentReadHeap=%d !\n", currentWriteHeap, currentReadHeap);
93108
}
109+
94110
void loop() {
111+
const uint32_t now = millis();
95112
//if (audio_sd_buffered_play_needs_loading) {
96-
// load from sd to audio buffers
113+
// load from sd to audio buffers
97114
//} else
98115
if (numLoaded < 4) {
99116
if (asyncOpening) {
@@ -106,62 +123,75 @@ void loop() {
106123
return;
107124
}
108125
asyncOpening = false;
109-
Serial.printf("loading '%s'... (heap:%d, index:%d)\n", filename, currentWriteHeap, numLoaded);
126+
Serial.printf("loading '%s'... (heap:%d, index:%d, pointer:%x)\t\t", filename, currentWriteHeap, numLoaded, samples[currentWriteHeap][numLoaded]->sampledata);
110127
} else if (loader.continueAsyncLoadPartial()) {
111-
Serial.printf("loading complete... (heap:%d, index:%d)\n", currentWriteHeap, numLoaded);
112128
numLoaded++;
113129
asyncLoadFile.close();
114130
asyncOpening = true;
115131
}
116132
} else if (!isPlaying) {
117133
isPlaying = true;
118134
Serial.println("Audio loaded, playback enabled!");
135+
136+
patternStartTime = now;
137+
//const uint32_t patternEndMillis = patternStartTime + durationOf32BeatsInMilliseconds;
138+
//Serial.printf("patternStartTime: %d patternEndTime: %d\n", patternStartTime, patternEndMillis);
119139
loader.toggle_beforeNewPatternVoicesStart();
120140
loader.toggle_afterNewPatternStarts();
121-
patternStartTime = millis();
122141
heap_switch();
123142
}
124143

125144
if (!isPlaying) return;
126145

127-
for (int i=0; i < 4; i++) {
128-
auto voice = voices[currentReadHeap][i];
129-
if (voice && !voice->isPlaying()) {
130-
newdigate::audiosample *sample = samples[currentReadHeap][i];
131-
voice->playRaw(sample->sampledata, sample->samplesize / 2, 1);
132-
Serial.printf("playing... (heap:%d, index:%d)\n", currentWriteHeap, i);
146+
if (!asyncChanging) { // dont play any new samples after the pre-pattern switch event
147+
for (int i=0; i < 4; i++) {
148+
auto voice = voices[currentReadHeap][i];
149+
if (voice && !voice->isPlaying()) {
150+
newdigate::audiosample *sample = samples[currentReadHeap][i];
151+
voice->playRaw(sample->sampledata, sample->samplesize / 2, 1);
152+
voice->setLoopStart(0);
153+
voice->setLoopFinish(sample->samplesize/2);
154+
voice->setLoopType(loop_type::looptype_repeat);
155+
Serial.printf("playing... (heap:%d, index:%d - size: %d)\t\t\t%x\n", currentReadHeap, i, sample->samplesize, sample->sampledata);
156+
}
133157
}
134158
}
135159

136-
const uint32_t now = millis();
137160
const uint32_t patternEndMillis = patternStartTime + durationOf32BeatsInMilliseconds;
138-
// 0.5 second before the next pattern starts to play, get ready
139-
if (now >= patternEndMillis - 500) {
140-
// current samples can keep playing
141-
if (!asyncChanging) {
142-
Serial.println("Pattern change coming soon!");
143-
loader.toggle_beforeNewPatternVoicesStart();
144-
asyncChanging = true;
145-
}
146-
} else if (now >= patternEndMillis) {
161+
if (now >= patternEndMillis) {
162+
Serial.println("Pattern switch");
147163
asyncChanging = false;
148164
for (int i=0; i < 4; i++) {
149165
auto voice = voices[currentReadHeap][i];
150-
if (!voice->isPlaying()) {
166+
if (voice && voice->isPlaying()) {
151167
voice->stop();
152168
}
153-
voices[currentReadHeap][i] = nullptr;
169+
//samples[currentReadHeap][i] = nullptr;
154170
}
155171
if (numLoaded < 4) {
156172
Serial.println("WARN: not all the samples managed to load in time!");
157173
}
158-
Serial.println("Audio loaded, playback enabled!");
174+
159175
loader.toggle_afterNewPatternStarts();
176+
160177
patternStartTime = now;
161178
heap_switch();
179+
} else if (now >= patternEndMillis - 500) {
180+
// 0.5 second before the next pattern starts to play, get ready
181+
// current samples can keep playing
182+
if (!asyncChanging) {
183+
Serial.println("pre-pattern switch event, pattern change coming soon!");
184+
loader.toggle_beforeNewPatternVoicesStart();
185+
asyncChanging = true;
186+
}
162187
}
188+
189+
// my thinking re: delay(1) is to give the mcu a some time between partial loads, not sure thou...
190+
delay(1);
163191
}
164192

165-
void std::__throw_length_error(char const*) {
166193

167-
}
194+
// this method below is needed for c++17 - it doesn't link otherwise, but for c++14 this is not needed:
195+
void std::__throw_length_error(char const*) {
196+
// don't worry, be happy!
197+
}

src/flashloader.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
#include <Arduino.h>
2727
#include <SD.h>
28+
#include <vector>
29+
#include <Audio.h>
2830

2931
extern "C" uint8_t external_psram_size;
3032

@@ -87,7 +89,8 @@ namespace newdigate {
8789
void reset() {
8890
// discard all samples, deallocate pointers
8991
for ( auto index : _samples) {
90-
free(index);
92+
if (index)
93+
free(index);
9194
}
9295
_samples.clear();
9396
_offset = 0;
@@ -109,8 +112,8 @@ namespace newdigate {
109112
heap_start2(heap_start + total_heap_size / 2 + 1),
110113
heap1(heap_start, total_heap_size / 2),
111114
heap2(heap_start2, total_heap_size / 2),
112-
_readHeap(&heap1),
113-
_writeHeap(&heap2) {
115+
_readHeap(&heap2),
116+
_writeHeap(&heap1) {
114117
_bytes_available = external_psram_size * 1048576 - heap_offset;
115118
}
116119
size_t _read_buffer_size;
@@ -131,16 +134,28 @@ namespace newdigate {
131134
auto size = _currentFile->size();
132135
file.seek(0);
133136
audiosample *sample = _writeHeap->allocate(size);
137+
if (!sample) {
138+
Serial.println("WARN: sample was not allocated");
139+
}
134140
_currentReadSample = sample;
135141
return sample;
136142
}
137143

138144
bool continueAsyncLoadPartial() {
139-
if (!_currentFile && _currentReadSample) {
140-
size_t bytesRead = _currentFile->read( _currentReadSample->sampledata + _currentSampleOffset , _read_buffer_size);
145+
if (_currentFile && _currentReadSample) {
146+
147+
//AudioNoInterrupts();
148+
size_t bytesRead = _currentFile->read( (int8_t*)_currentReadSample->sampledata + _currentSampleOffset, _read_buffer_size);
149+
//AudioInterrupts();
150+
141151
_currentSampleOffset += bytesRead;
142-
if (bytesRead == _read_buffer_size)
152+
if (bytesRead == _read_buffer_size) {
143153
return false; // return false because the sample is not completed loading
154+
} else {
155+
Serial.printf("Complete! totalBytesRead: %d, pointer: %x\n", _currentSampleOffset, _currentReadSample->sampledata);
156+
_currentSampleOffset = 0;
157+
return true;
158+
}
144159
};
145160

146161
_currentSampleOffset = 0; //reset this value for the next sample!
@@ -155,9 +170,11 @@ namespace newdigate {
155170
// 4. call toggle_afterNewPatternStarts()
156171
void toggle_beforeNewPatternVoicesStart() {
157172
// switch the read and write heap
173+
//AudioNoInterrupts();
158174
audio_chunk_heap *temp = _readHeap;
159175
_readHeap = _writeHeap;
160176
_writeHeap = temp;
177+
// AudioInterrupts();
161178
}
162179

163180
void toggle_afterNewPatternStarts() const {

0 commit comments

Comments
 (0)