@@ -134,7 +134,7 @@ class MemoryStream : public AudioStream {
134134 return begin ();
135135 }
136136
137- // / resets the read pointer
137+ // / resets the read pointer and write pointer if the memory is changeable
138138 bool begin () override {
139139 TRACED ();
140140 write_pos = memoryCanChange () ? 0 : buffer_size;
@@ -146,6 +146,13 @@ class MemoryStream : public AudioStream {
146146 return is_active;
147147 }
148148
149+ // / Resets the read pointer
150+ void rewind () {
151+ if (buffer != nullptr && buffer_size > 0 ) {
152+ read_pos = 0 ;
153+ }
154+ }
155+
149156 virtual size_t write (uint8_t byte) override {
150157 if (!is_active) return 0 ;
151158 if (memory_type == FLASH_RAM) return 0 ;
@@ -181,7 +188,7 @@ class MemoryStream : public AudioStream {
181188 read_pos = rewind_pos;
182189 result = write_pos - read_pos;
183190 // call callback
184- if (rewind != nullptr ) rewind ();
191+ if (rewind_cb != nullptr ) rewind_cb ();
185192 }
186193 return is_loop ? DEFAULT_BUFFER_SIZE : result;
187194 }
@@ -290,10 +297,17 @@ class MemoryStream : public AudioStream {
290297 virtual uint8_t *data () { return buffer; }
291298
292299 // / update the write_pos (e.g. when we used data() to update the array)
293- virtual void setAvailable (size_t len) { this ->write_pos = len; }
300+ virtual bool setAvailable (size_t len) {
301+ if (len <= buffer_size) {
302+ write_pos = len;
303+ if (read_pos > write_pos) read_pos = write_pos;
304+ return true ;
305+ }
306+ return false ;
307+ }
294308
295309 // / Callback which is executed when we rewind (in loop mode) to the beginning
296- void setRewindCallback (void (*cb)()) { this ->rewind = cb; }
310+ void setRewindCallback (void (*cb)()) { this ->rewind_cb = cb; }
297311
298312 // / Update the values (buffer and size)
299313 void setValue (const uint8_t *buffer, int buffer_size,
@@ -313,21 +327,52 @@ class MemoryStream : public AudioStream {
313327 uint8_t *buffer = nullptr ;
314328 MemoryType memory_type = RAM;
315329 bool is_loop = false ;
316- void (*rewind )() = nullptr ;
330+ void (*rewind_cb )() = nullptr ;
317331 bool is_active = false ;
318332 bool owns_memory = true ;
319333
320334 bool memoryCanChange () { return memory_type != FLASH_RAM; }
321335
322336 void copy (MemoryStream &source) {
323337 if (this == &source) return ;
338+
339+ // Release currently owned mutable buffer.
340+ if (memoryCanChange () && owns_memory && buffer != nullptr ) {
341+ free (buffer);
342+ buffer = nullptr ;
343+ }
344+
345+ // Shallow copy for FLASH memory source.
324346 if (source.memory_type == FLASH_RAM) {
347+ owns_memory = false ;
325348 setValue (source.buffer , source.buffer_size , source.memory_type );
326- } else {
327- setValue (nullptr , source.buffer_size , source.memory_type );
328- resize (buffer_size);
329- memcpy (buffer, source.buffer , buffer_size);
349+ is_active = source.is_active ;
350+ is_loop = source.is_loop ;
351+ rewind_pos = source.rewind_pos ;
352+ return ;
353+ }
354+
355+ // Deep copy for mutable source memory.
356+ owns_memory = true ;
357+ setValue (nullptr , source.buffer_size , source.memory_type );
358+ if (!resize (source.buffer_size )) {
359+ setValue (nullptr , 0 , source.memory_type );
360+ is_active = false ;
361+ return ;
362+ }
363+
364+ if (source.buffer != nullptr && source.buffer_size > 0 ) {
365+ memcpy (buffer, source.buffer , source.buffer_size );
330366 }
367+
368+ write_pos = source.write_pos ;
369+ read_pos = source.read_pos ;
370+ if (write_pos > buffer_size) write_pos = buffer_size;
371+ if (read_pos > write_pos) read_pos = write_pos;
372+
373+ is_active = source.is_active ;
374+ is_loop = source.is_loop ;
375+ rewind_pos = source.rewind_pos ;
331376 }
332377};
333378
0 commit comments