Skip to content

Commit

Permalink
Merge pull request #53 from newdigate/feature/play_start
Browse files Browse the repository at this point in the history
Feature: play start option
  • Loading branch information
newdigate authored Feb 26, 2023
2 parents 04605a9 + 3fa59fc commit f9e1565
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 22 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@ play 16-bit PCM raw or wav audio samples at variable playback rates on teensy
* [sd classes on wikipedia](https://en.wikipedia.org/wiki/SD_card#cite_ref-93)

## updates
* 26/02/2022: v1.0.16:
* add option for starting sample at begining or at loop start
``` c
typedef enum play_start {
play_start_sample,
play_start_loop,
};

wave.setPlayStart(play_start::play_start_loop);
```
* 26/02/2022: v1.0.15:
* added support for dual playback head for seemless looping
* enable dual playback using linear crossfading
* set crossfade duration in number of samples
```
``` c
AudioPlaySdResmp wave;
wave.setUseDualPlaybackHead(true);
wave.setCrossfadeDurationInSamples(1000);
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"keywords": "sound, audio, sample, resample, pitch, interpolation, legrange, sampler, playback, speed, loop",
"description": "Teensy Variable Playback",
"url": "https://github.com/newdigate/teensy-variable-playback",
"version": "1.0.15",
"version": "1.0.16",
"export": {
"exclude": [
".vscode",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=TeensyVariablePlayback
version=1.0.15
version=1.0.16
author=Nic Newdigate
maintainer=Nic Newdigate
sentence=Play samples at variable pitch using Teensy Audio Library
Expand Down
79 changes: 60 additions & 19 deletions src/ResamplingReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ class ResamplingReader {
}
_playing = false;
_crossfade = 0.0;
_bufferPosition1 = _header_offset;
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _header_offset;
else
_bufferPosition1 = _loop_start;
_file_size = 0;
}

Expand Down Expand Up @@ -190,11 +193,12 @@ class ResamplingReader {
{
if (_playbackRate >= 0.0) {
_bufferPosition1 = _loop_finish - _numChannels;
//printf("switching to reverse playback...\n");
}
else {
_bufferPosition1 = _header_offset;
//printf("switching to forward playback...\n");
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _header_offset;
else
_bufferPosition1 = _loop_start;
}
_playbackRate = -_playbackRate;
break;
Expand Down Expand Up @@ -223,9 +227,14 @@ class ResamplingReader {
if (_bufferPosition1 >= _loop_finish )
return false;
} else if (_playbackRate < 0) {
// reverse playback
if (_bufferPosition1 < _header_offset)
return false;
// reverse playback
if (_play_start == play_start::play_start_sample) {
if (_bufferPosition1 < _header_offset)
return false;
} else {
if (_bufferPosition1 < _loop_start)
return false;
}
}
} else {
if (_playbackRate >= 0.0) {
Expand Down Expand Up @@ -427,9 +436,36 @@ class ResamplingReader {
void setPlaybackRate(double f) {
_playbackRate = f;
if (!_useDualPlaybackHead) {
if (f < 0.0 && _bufferPosition1 == 0) {
//_file.seek(_file_size);
_bufferPosition1 = _file_size/2 - _numChannels;
if (f < 0.0) {
if (_bufferPosition1 <= _header_offset) {
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _file_size/2 - _numChannels;
else
_bufferPosition1 = _loop_finish - _numChannels;
}
} else {
if (f >= 0.0 && _bufferPosition1 < _header_offset) {
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _header_offset;
else
_bufferPosition1 = _loop_start;
}
}
} else {
// _useDualPlaybackHead == true
if (_crossfade == 0.0) {
if (f < 0.0) {
if( _bufferPosition1 <= _header_offset) {
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _file_size/2 - _numChannels;
else
_bufferPosition1 = _loop_finish - _numChannels;
}
} else {
if (f >= 0.0 && _bufferPosition1 < _header_offset) {
_bufferPosition1 = _header_offset;
}
}
}
}
}
Expand Down Expand Up @@ -465,10 +501,16 @@ class ResamplingReader {
_numInterpolationPoints = 0;
if (_playbackRate > 0.0) {
// forward playabck - set _file_offset to first audio block in file
_bufferPosition1 = _header_offset;
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _header_offset;
else
_bufferPosition1 = _loop_start;
} else {
// reverse playback - forward _file_offset to last audio block in file
_bufferPosition1 = _loop_finish - _numChannels;
if (_play_start == play_start::play_start_sample)
_bufferPosition1 = _file_size/2 - _numChannels;
else
_bufferPosition1 = _loop_finish - _numChannels;
}
_crossfade = 0.0;
}
Expand Down Expand Up @@ -510,14 +552,12 @@ class ResamplingReader {

void setHeaderSizeInBytes(uint32_t headerSizeInBytes) {
_header_offset = headerSizeInBytes / 2;
if (_bufferPosition1 < _header_offset) {
if (_playbackRate >= 0) {
_bufferPosition1 = _header_offset;
} else
_bufferPosition1 = _loop_finish - _numChannels;
}
}

void setPlayStart(play_start start) {
_play_start = start;
}

#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592
uint32_t positionMillis()
{
Expand All @@ -537,7 +577,8 @@ class ResamplingReader {

double _playbackRate = 1.0;
double _remainder = 0.0;
loop_type _loopType = looptype_none;
loop_type _loopType = loop_type::looptype_none;
play_start _play_start = play_start::play_start_sample;
int _bufferPosition1 = 0;
int _bufferPosition2 = 0;
double _crossfade = 0.0;
Expand Down
5 changes: 5 additions & 0 deletions src/loop_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ typedef enum loop_type {
looptype_pingpong
} loop_type;

typedef enum play_start {
play_start_sample,
play_start_loop,
} play_start;

#endif //TEENSY_RESAMPLING_LOOP_TYPE_H
4 changes: 4 additions & 0 deletions src/playresmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ class AudioPlayResmp : public AudioStream
reader->setCrossfadeDurationInSamples(crossfadeDurationInSamples);
}

void setPlayStart(play_start start) {
reader->setPlayStart(start);
}

void enableInterpolation(bool enable) {
if (enable)
reader->setInterpolationType(ResampleInterpolationType::resampleinterpolation_quadratic);
Expand Down

0 comments on commit f9e1565

Please sign in to comment.