1
+ #pragma once
2
+
3
+ #include " AudioTools/AudioStreams.h"
4
+ #include " FS.h"
5
+
6
+ namespace audio_tools {
7
+
8
+ /* *
9
+ * @brief A simple class which implements a automatic looping file.
10
+ * In order to support different file implementation the file class
11
+ * is a template parameter. The number of loops can be defined by
12
+ * calling setLoopCount().
13
+ * You can also optinally limit the total looping file size by calling
14
+ * setSize();
15
+ * @ingroup io
16
+ * @author Phil Schatzmann
17
+ * @copyright GPLv3
18
+ */
19
+ template <class FileType > class FileLoopT : public AudioStream {
20
+ public:
21
+ FileLoopT () = default ;
22
+ FileLoopT (FileType file, int count = -1 , int rewindPos = 0 ) {
23
+ setFile (file);
24
+ setLoopCount (count);
25
+ setStartPos (rewindPos);
26
+ }
27
+
28
+ // restarts the file from the beginning
29
+ bool begin () override {
30
+ TRACEI ();
31
+ current_file.seek (start_pos);
32
+ size_open = total_size;
33
+ return current_file;
34
+ }
35
+
36
+ // closes the file
37
+ void end () override {
38
+ TRACEI ();
39
+ current_file.close ();
40
+ }
41
+
42
+ // / defines the file that is used for looping
43
+ void setFile (FileType file) { this ->current_file = file; }
44
+
45
+ // / Returns the file
46
+ FileType &file (){
47
+ return current_file;
48
+ }
49
+
50
+ // / defines the start position after the rewind. E.g. for wav files this should be 44
51
+ void setStartPos (int pos) { start_pos = pos; }
52
+
53
+ // / defines the requested playing size in bytes
54
+ void setSize (size_t len) {
55
+ total_size = len;
56
+ }
57
+
58
+ // / You can be notified about a rewind
59
+ void setCallback (void (*cb)(FileLoopT &loop)){
60
+ callback = cb;
61
+ }
62
+
63
+ // / count values: 0) do not loop, 1) loop once, n) loop n times, -1) loop
64
+ // / endless
65
+ void setLoopCount (int count) { loop_count = count; }
66
+
67
+ int available () override {
68
+ // if we manage the size, we return the open amount
69
+ if (total_size!=-1 ) return size_open;
70
+ // otherwise we return DEFAULT_BUFFER_SIZE if looping is active
71
+ return isLoopActive () ? DEFAULT_BUFFER_SIZE : current_file.available ();
72
+ }
73
+
74
+ size_t readBytes (uint8_t *data, size_t len) {
75
+ LOGD (" FileLoopT::readBytes %d at %d" , len, current_file.position ());
76
+ if (!current_file)
77
+ return 0 ;
78
+
79
+ // limit the copy size if necessary
80
+ int copy_len = len;
81
+ if (total_size!=-1 ){
82
+ copy_len = min ((int )len, size_open);
83
+ }
84
+
85
+ // read step 1;
86
+ int result1 = current_file.readBytes ((char *)data, copy_len);
87
+ int result2 = 0 ;
88
+ int open = copy_len - result1;
89
+ if (isLoopActive () && open>0 ) {
90
+ LOGI (" seek 0" );
91
+ // looping logic -> rewind to beginning: read step 2
92
+ current_file.seek (start_pos);
93
+ // notify user
94
+ if (callback!=nullptr ){
95
+ callback (*this );
96
+ }
97
+ result1 = current_file.readBytes ((char *)data + result1, open);
98
+ if (loop_count>0 )
99
+ loop_count--;
100
+ }
101
+ // determine the result size
102
+ int result = result1 + result2;
103
+ // calculate the size_open if necessary
104
+ if (total_size!=-1 ){
105
+ size_open -= result;
106
+ }
107
+ return result;
108
+ }
109
+
110
+ operator bool () {
111
+ return current_file;
112
+ }
113
+
114
+ // / Returns the (requested) file size
115
+ size_t size () {
116
+ return total_size == -1 ? current_file.size () : total_size;
117
+ }
118
+
119
+ // / @return true as long as we are looping
120
+ bool isLoopActive () { return loop_count > 0 || loop_count == -1 ; }
121
+
122
+ protected:
123
+ int start_pos = 0 ;
124
+ int loop_count = -1 ;
125
+ int size_open = -1 ;
126
+ int total_size = -1 ;
127
+ void (*callback)(FileLoopT &loop) = nullptr ;
128
+ FileType current_file;
129
+ };
130
+
131
+ /* *
132
+ * @brief A simple class which implements a automatic looping file.
133
+ * The file needs to be of the class File from FS.h. The number of loops can be
134
+ * defined by calling setLoopCount().
135
+ * You can also optinally limit the total looping file size by calling
136
+ * setSize();
137
+ * @ingroup io
138
+ * @author Phil Schatzmann
139
+ * @copyright GPLv3
140
+ */
141
+
142
+ class FileLoop : public FileLoopT <File> {
143
+ public:
144
+ FileLoop () = default ;
145
+ FileLoop (File file, int count = -1 , int rewindPos = 0 )
146
+ : FileLoopT<File>(file, count, rewindPos) {}
147
+ };
148
+
149
+ } // namespace audio_tools
0 commit comments