arduino-audio-tools
FileLoop.h
1 #pragma once
2 
3 #include "AudioTools/CoreAudio/BaseStream.h"
4 #include "AudioTools/CoreAudio/AudioBasic/StrView.h"
5 #ifdef ARDUINO
6 # include "FS.h"
7 # define READTYPE char
8 #else
9 # define READTYPE uint8_t
10 #endif
11 namespace audio_tools {
12 
24 template <class FileType> class FileLoopT : public BaseStream {
25 public:
26  FileLoopT() = default;
27  FileLoopT(FileType file, int count = -1, int rewindPos = -1) {
28  setFile(file);
29  setLoopCount(count);
30  setStartPos(rewindPos);
31  }
32 
33  // restarts the file from the beginning
34  bool begin() {
35  TRACEI();
36  // automatic determination of start pos
37  if (start_pos <= 0){
38  current_file.seek(0);
39  char tmp[5] = {0};
40  current_file.readBytes(tmp, 4);
41  // for wav files remove header
42  start_pos = StrView(tmp).equals("RIFF") ? 44 : 0;
43  current_file.seek(0);
44  } else {
45  current_file.seek(start_pos);
46  }
47  size_open = total_size;
48  return current_file;
49  }
50 
51  // closes the file
52  void end() {
53  TRACEI();
54  current_file.close();
55  }
56 
58  void setFile(FileType file) { this->current_file = file; }
59 
61  FileType &file(){
62  return current_file;
63  }
64 
66  void setStartPos(int pos) { start_pos = pos; }
67 
69  void setSize(size_t len) {
70  total_size = len;
71  }
72 
74  size_t size() {
75  return total_size == -1 ? current_file.size() : total_size;
76  }
77 
79  void setCallback(void (*cb)(FileLoopT &loop)){
80  callback = cb;
81  }
82 
85  void setLoopCount(int count) { loop_count = count; }
86 
87  int available() override {
88  // if we manage the size, we return the open amount
89  if (total_size!=-1) return size_open;
90  // otherwise we return DEFAULT_BUFFER_SIZE if looping is active
91  return isLoopActive() ? DEFAULT_BUFFER_SIZE : current_file.available();
92  }
93 
94  size_t readBytes(uint8_t *data, size_t len) override {
95  LOGD("FileLoopT::readBytes %d at %d", (int)len, (int)current_file.position());
96  if (!current_file)
97  return 0;
98 
99  // limit the copy size if necessary
100  int copy_len = len;
101  if (total_size!=-1){
102  copy_len = min((int)len, size_open);
103  }
104 
105  // read step 1;
106  int result1 = current_file.readBytes((READTYPE *)data, copy_len);
107  int result2 = 0;
108  int open = copy_len - result1;
109  if (isLoopActive() && open > 0) {
110  if (start_pos < 0) start_pos = 0;
111  LOGI("seek %d", start_pos);
112  // looping logic -> rewind to beginning: read step 2
113  current_file.seek(start_pos);
114  // notify user
115  if (callback!=nullptr){
116  callback(*this);
117  }
118  result1 = current_file.readBytes((READTYPE*)data + result1, open);
119  if (loop_count>0)
120  loop_count--;
121  }
122  // determine the result size
123  int result = result1 + result2;
124  // calculate the size_open if necessary
125  if (total_size!=-1){
126  size_open -= result;
127  }
128  return result;
129  }
130 
131  // Returns the bool of the current file
132  operator bool() {
133  return current_file;
134  }
135 
137  bool isLoopActive() { return loop_count > 0 || loop_count == -1; }
138 
139  size_t write(const uint8_t* data, size_t len) { return current_file.write(data, len);}
140 
141 protected:
142  int start_pos = -1;
143  int loop_count = -1;
144  int size_open = -1;
145  int total_size = -1;
146  void (*callback)(FileLoopT &loop) = nullptr;
147  FileType current_file;
148 };
149 
161 class FileLoop : public FileLoopT<File> {
162 public:
163  FileLoop() = default;
164  FileLoop(File file, int count = -1, int rewindPos = 0)
165  : FileLoopT<File>(file, count, rewindPos) {}
166 };
167 
168 } // namespace audio_tools
Base class for all Streams. It relies on write(const uint8_t *buffer, size_t size) and readBytes(uint...
Definition: BaseStream.h:34
Arduino File support using std::fstream.
Definition: File.h:25
A simple class which implements a automatic looping file. The file needs to be of the class File from...
Definition: FileLoop.h:161
A simple class which implements a automatic looping file. In order to support different file implemen...
Definition: FileLoop.h:24
size_t size()
Returns the (requested) file size.
Definition: FileLoop.h:74
void setLoopCount(int count)
Definition: FileLoop.h:85
void setFile(FileType file)
defines the file that is used for looping
Definition: FileLoop.h:58
void setStartPos(int pos)
defines the start position after the rewind. E.g. for wav files this should be 44
Definition: FileLoop.h:66
void setCallback(void(*cb)(FileLoopT &loop))
You can be notified about a rewind.
Definition: FileLoop.h:79
bool isLoopActive()
Definition: FileLoop.h:137
void setSize(size_t len)
optionally defines the requested playing size in bytes
Definition: FileLoop.h:69
FileType & file()
Returns the file.
Definition: FileLoop.h:61
A simple wrapper to provide string functions on existing allocated char*. If the underlying char* is ...
Definition: StrView.h:28
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition: StrView.h:165
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:868