test public
Dependencies: HttpServer_snapshot_mbed-os
mbed-gr-libs/EasyPlayback/EasyPlayback.cpp@0:e9fd5575b10e, 2019-10-18 (annotated)
- Committer:
- anhtran
- Date:
- Fri Oct 18 03:09:43 2019 +0000
- Revision:
- 0:e9fd5575b10e
abc
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
anhtran | 0:e9fd5575b10e | 1 | /* mbed EasyPlayback Library |
anhtran | 0:e9fd5575b10e | 2 | * Copyright (C) 2017 dkato |
anhtran | 0:e9fd5575b10e | 3 | * |
anhtran | 0:e9fd5575b10e | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
anhtran | 0:e9fd5575b10e | 5 | * you may not use this file except in compliance with the License. |
anhtran | 0:e9fd5575b10e | 6 | * You may obtain a copy of the License at |
anhtran | 0:e9fd5575b10e | 7 | * |
anhtran | 0:e9fd5575b10e | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
anhtran | 0:e9fd5575b10e | 9 | * |
anhtran | 0:e9fd5575b10e | 10 | * Unless required by applicable law or agreed to in writing, software |
anhtran | 0:e9fd5575b10e | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
anhtran | 0:e9fd5575b10e | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
anhtran | 0:e9fd5575b10e | 13 | * See the License for the specific language governing permissions and |
anhtran | 0:e9fd5575b10e | 14 | * limitations under the License. |
anhtran | 0:e9fd5575b10e | 15 | */ |
anhtran | 0:e9fd5575b10e | 16 | |
anhtran | 0:e9fd5575b10e | 17 | #include "mbed.h" |
anhtran | 0:e9fd5575b10e | 18 | #include "dcache-control.h" |
anhtran | 0:e9fd5575b10e | 19 | #include "EasyPlayback.h" |
anhtran | 0:e9fd5575b10e | 20 | |
anhtran | 0:e9fd5575b10e | 21 | EasyPlayback::EasyPlayback(audio_type_t type, PinName pin1, PinName pin2) : |
anhtran | 0:e9fd5575b10e | 22 | _buff_index(0), _type(type), _skip(false), _pause(false), _init_end(false) |
anhtran | 0:e9fd5575b10e | 23 | { |
anhtran | 0:e9fd5575b10e | 24 | _audio_buff_size = 0; |
anhtran | 0:e9fd5575b10e | 25 | _audio_write_buff_num = 0; |
anhtran | 0:e9fd5575b10e | 26 | _audio_ssif = NULL; |
anhtran | 0:e9fd5575b10e | 27 | _audio_pwm = NULL; |
anhtran | 0:e9fd5575b10e | 28 | #if (R_BSP_SPDIF_ENABLE == 1) |
anhtran | 0:e9fd5575b10e | 29 | _audio_spdif = NULL; |
anhtran | 0:e9fd5575b10e | 30 | #endif |
anhtran | 0:e9fd5575b10e | 31 | _audio_soundless = NULL; |
anhtran | 0:e9fd5575b10e | 32 | _heap_buf = NULL; |
anhtran | 0:e9fd5575b10e | 33 | _audio_buf = NULL; |
anhtran | 0:e9fd5575b10e | 34 | if (_type == AUDIO_TPYE_SSIF) { |
anhtran | 0:e9fd5575b10e | 35 | _audio_buff_size = 4096; |
anhtran | 0:e9fd5575b10e | 36 | _audio_write_buff_num = 8; |
anhtran | 0:e9fd5575b10e | 37 | _audio_ssif = new AUDIO_GRBoard(0x80, (_audio_write_buff_num - 1), 0); |
anhtran | 0:e9fd5575b10e | 38 | _audio = _audio_ssif; |
anhtran | 0:e9fd5575b10e | 39 | } else if (_type == AUDIO_TPYE_PWM) { |
anhtran | 0:e9fd5575b10e | 40 | _audio_buff_size = 4096; |
anhtran | 0:e9fd5575b10e | 41 | _audio_write_buff_num = 8; |
anhtran | 0:e9fd5575b10e | 42 | _audio_pwm = new PwmOutSpeaker(pin1, pin2); |
anhtran | 0:e9fd5575b10e | 43 | _audio = _audio_pwm; |
anhtran | 0:e9fd5575b10e | 44 | } else if (_type == AUDIO_TPYE_SPDIF) { |
anhtran | 0:e9fd5575b10e | 45 | #if (R_BSP_SPDIF_ENABLE == 1) |
anhtran | 0:e9fd5575b10e | 46 | _audio_buff_size = (192 * 2 * 10); |
anhtran | 0:e9fd5575b10e | 47 | _audio_write_buff_num = 8; |
anhtran | 0:e9fd5575b10e | 48 | _audio_spdif = new SPDIF_GRBoard(0x80, (_audio_write_buff_num - 1), 0); |
anhtran | 0:e9fd5575b10e | 49 | _audio = _audio_spdif; |
anhtran | 0:e9fd5575b10e | 50 | #else |
anhtran | 0:e9fd5575b10e | 51 | MBED_ASSERT(false); |
anhtran | 0:e9fd5575b10e | 52 | #endif |
anhtran | 0:e9fd5575b10e | 53 | } else if (_type == AUDIO_TPYE_SOUNDLESS) { |
anhtran | 0:e9fd5575b10e | 54 | _audio_buff_size = (4410 * 2); |
anhtran | 0:e9fd5575b10e | 55 | _audio_write_buff_num = 0; |
anhtran | 0:e9fd5575b10e | 56 | _audio_soundless = new SoundlessSpeaker(); |
anhtran | 0:e9fd5575b10e | 57 | _audio = _audio_soundless; |
anhtran | 0:e9fd5575b10e | 58 | } else if (_type == AUDIO_TPYE_NULL) { |
anhtran | 0:e9fd5575b10e | 59 | _audio_buff_size = 4096; |
anhtran | 0:e9fd5575b10e | 60 | _audio_write_buff_num = 0; |
anhtran | 0:e9fd5575b10e | 61 | _audio_null = new NullSpeaker(); |
anhtran | 0:e9fd5575b10e | 62 | _audio = _audio_null; |
anhtran | 0:e9fd5575b10e | 63 | } else { |
anhtran | 0:e9fd5575b10e | 64 | MBED_ASSERT(false); |
anhtran | 0:e9fd5575b10e | 65 | } |
anhtran | 0:e9fd5575b10e | 66 | if ((_audio_buff_size != 0) && (_audio_write_buff_num != 0)) { |
anhtran | 0:e9fd5575b10e | 67 | _heap_buf = new uint8_t[_audio_buff_size * _audio_write_buff_num + 31]; |
anhtran | 0:e9fd5575b10e | 68 | _audio_buf = (uint8_t *)(((uint32_t)_heap_buf + 31ul) & ~31ul); |
anhtran | 0:e9fd5575b10e | 69 | } |
anhtran | 0:e9fd5575b10e | 70 | } |
anhtran | 0:e9fd5575b10e | 71 | |
anhtran | 0:e9fd5575b10e | 72 | EasyPlayback::~EasyPlayback() |
anhtran | 0:e9fd5575b10e | 73 | { |
anhtran | 0:e9fd5575b10e | 74 | if (_audio_ssif != NULL) { |
anhtran | 0:e9fd5575b10e | 75 | delete _audio_ssif; |
anhtran | 0:e9fd5575b10e | 76 | } |
anhtran | 0:e9fd5575b10e | 77 | if (_audio_pwm != NULL) { |
anhtran | 0:e9fd5575b10e | 78 | delete _audio_pwm; |
anhtran | 0:e9fd5575b10e | 79 | } |
anhtran | 0:e9fd5575b10e | 80 | #if (R_BSP_SPDIF_ENABLE == 1) |
anhtran | 0:e9fd5575b10e | 81 | if (_audio_spdif != NULL) { |
anhtran | 0:e9fd5575b10e | 82 | delete _audio_spdif; |
anhtran | 0:e9fd5575b10e | 83 | } |
anhtran | 0:e9fd5575b10e | 84 | #endif |
anhtran | 0:e9fd5575b10e | 85 | if (_audio_soundless != NULL) { |
anhtran | 0:e9fd5575b10e | 86 | delete _audio_soundless; |
anhtran | 0:e9fd5575b10e | 87 | } |
anhtran | 0:e9fd5575b10e | 88 | if (_heap_buf != NULL) { |
anhtran | 0:e9fd5575b10e | 89 | delete [] _heap_buf; |
anhtran | 0:e9fd5575b10e | 90 | } |
anhtran | 0:e9fd5575b10e | 91 | } |
anhtran | 0:e9fd5575b10e | 92 | |
anhtran | 0:e9fd5575b10e | 93 | bool EasyPlayback::get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size) |
anhtran | 0:e9fd5575b10e | 94 | { |
anhtran | 0:e9fd5575b10e | 95 | FILE * fp = NULL; |
anhtran | 0:e9fd5575b10e | 96 | EasyDecoder * decoder; |
anhtran | 0:e9fd5575b10e | 97 | bool ret = false; |
anhtran | 0:e9fd5575b10e | 98 | |
anhtran | 0:e9fd5575b10e | 99 | decoder = create_decoer_class(filename); |
anhtran | 0:e9fd5575b10e | 100 | if (decoder == NULL) { |
anhtran | 0:e9fd5575b10e | 101 | return false; |
anhtran | 0:e9fd5575b10e | 102 | } |
anhtran | 0:e9fd5575b10e | 103 | |
anhtran | 0:e9fd5575b10e | 104 | fp = fopen(filename, "r"); |
anhtran | 0:e9fd5575b10e | 105 | if (fp == NULL) { |
anhtran | 0:e9fd5575b10e | 106 | // do nothing |
anhtran | 0:e9fd5575b10e | 107 | } else if (decoder->AnalyzeHeder(p_title, p_artist, p_album, tag_size, fp) != false) { |
anhtran | 0:e9fd5575b10e | 108 | ret = true; |
anhtran | 0:e9fd5575b10e | 109 | } |
anhtran | 0:e9fd5575b10e | 110 | delete decoder; |
anhtran | 0:e9fd5575b10e | 111 | if (fp != NULL) { |
anhtran | 0:e9fd5575b10e | 112 | fclose(fp); |
anhtran | 0:e9fd5575b10e | 113 | } |
anhtran | 0:e9fd5575b10e | 114 | |
anhtran | 0:e9fd5575b10e | 115 | return ret; |
anhtran | 0:e9fd5575b10e | 116 | } |
anhtran | 0:e9fd5575b10e | 117 | |
anhtran | 0:e9fd5575b10e | 118 | bool EasyPlayback::play(const char* filename) |
anhtran | 0:e9fd5575b10e | 119 | { |
anhtran | 0:e9fd5575b10e | 120 | const rbsp_data_conf_t audio_write_async_ctl = {NULL, NULL}; |
anhtran | 0:e9fd5575b10e | 121 | size_t audio_data_size; |
anhtran | 0:e9fd5575b10e | 122 | FILE * fp = NULL; |
anhtran | 0:e9fd5575b10e | 123 | uint8_t * p_buf; |
anhtran | 0:e9fd5575b10e | 124 | uint32_t read_size; |
anhtran | 0:e9fd5575b10e | 125 | uint32_t i; |
anhtran | 0:e9fd5575b10e | 126 | EasyDecoder * decoder; |
anhtran | 0:e9fd5575b10e | 127 | bool ret = false; |
anhtran | 0:e9fd5575b10e | 128 | uint32_t padding_size; |
anhtran | 0:e9fd5575b10e | 129 | |
anhtran | 0:e9fd5575b10e | 130 | decoder = create_decoer_class(filename); |
anhtran | 0:e9fd5575b10e | 131 | if (decoder == NULL) { |
anhtran | 0:e9fd5575b10e | 132 | return false; |
anhtran | 0:e9fd5575b10e | 133 | } |
anhtran | 0:e9fd5575b10e | 134 | |
anhtran | 0:e9fd5575b10e | 135 | if (!_init_end) { |
anhtran | 0:e9fd5575b10e | 136 | _audio->power(); |
anhtran | 0:e9fd5575b10e | 137 | _audio->outputVolume(1.0, 1.0); |
anhtran | 0:e9fd5575b10e | 138 | _init_end = true; |
anhtran | 0:e9fd5575b10e | 139 | } |
anhtran | 0:e9fd5575b10e | 140 | |
anhtran | 0:e9fd5575b10e | 141 | _skip = false; |
anhtran | 0:e9fd5575b10e | 142 | fp = fopen(filename, "r"); |
anhtran | 0:e9fd5575b10e | 143 | if (fp == NULL) { |
anhtran | 0:e9fd5575b10e | 144 | // do nothing |
anhtran | 0:e9fd5575b10e | 145 | } else if (decoder->AnalyzeHeder(NULL, NULL, NULL, 0, fp) == false) { |
anhtran | 0:e9fd5575b10e | 146 | // do nothing |
anhtran | 0:e9fd5575b10e | 147 | } else if ((decoder->GetChannel() != 2) |
anhtran | 0:e9fd5575b10e | 148 | || (_audio->format(decoder->GetBlockSize()) == false) |
anhtran | 0:e9fd5575b10e | 149 | || (_audio->frequency(decoder->GetSamplingRate()) == false)) { |
anhtran | 0:e9fd5575b10e | 150 | // do nothing |
anhtran | 0:e9fd5575b10e | 151 | } else { |
anhtran | 0:e9fd5575b10e | 152 | if ((_type == AUDIO_TPYE_SPDIF) && (decoder->GetBlockSize() == 16)) { |
anhtran | 0:e9fd5575b10e | 153 | padding_size = 2; |
anhtran | 0:e9fd5575b10e | 154 | read_size = _audio_buff_size / 2; |
anhtran | 0:e9fd5575b10e | 155 | } else if ((decoder->GetBlockSize() == 20) || (decoder->GetBlockSize() == 24)) { |
anhtran | 0:e9fd5575b10e | 156 | padding_size = 1; |
anhtran | 0:e9fd5575b10e | 157 | read_size = _audio_buff_size * 3 / 4; |
anhtran | 0:e9fd5575b10e | 158 | } else { |
anhtran | 0:e9fd5575b10e | 159 | padding_size = 0; |
anhtran | 0:e9fd5575b10e | 160 | read_size = _audio_buff_size; |
anhtran | 0:e9fd5575b10e | 161 | } |
anhtran | 0:e9fd5575b10e | 162 | setvbuf(fp, NULL, _IONBF, 0); // unbuffered |
anhtran | 0:e9fd5575b10e | 163 | |
anhtran | 0:e9fd5575b10e | 164 | while (true) { |
anhtran | 0:e9fd5575b10e | 165 | while ((_pause) && (!_skip)) { |
anhtran | 0:e9fd5575b10e | 166 | ThisThread::sleep_for(100); |
anhtran | 0:e9fd5575b10e | 167 | } |
anhtran | 0:e9fd5575b10e | 168 | if (_skip) { |
anhtran | 0:e9fd5575b10e | 169 | break; |
anhtran | 0:e9fd5575b10e | 170 | } |
anhtran | 0:e9fd5575b10e | 171 | if (_audio_buf == NULL) { |
anhtran | 0:e9fd5575b10e | 172 | audio_data_size = decoder->GetNextData(NULL, read_size); |
anhtran | 0:e9fd5575b10e | 173 | if (audio_data_size > 0) { |
anhtran | 0:e9fd5575b10e | 174 | if (padding_size != 0) { |
anhtran | 0:e9fd5575b10e | 175 | _audio->write(NULL, _audio_buff_size, &audio_write_async_ctl); |
anhtran | 0:e9fd5575b10e | 176 | } else { |
anhtran | 0:e9fd5575b10e | 177 | _audio->write(NULL, audio_data_size, &audio_write_async_ctl); |
anhtran | 0:e9fd5575b10e | 178 | } |
anhtran | 0:e9fd5575b10e | 179 | } else { |
anhtran | 0:e9fd5575b10e | 180 | break; |
anhtran | 0:e9fd5575b10e | 181 | } |
anhtran | 0:e9fd5575b10e | 182 | } else { |
anhtran | 0:e9fd5575b10e | 183 | p_buf = &_audio_buf[_audio_buff_size * _buff_index]; |
anhtran | 0:e9fd5575b10e | 184 | audio_data_size = decoder->GetNextData(p_buf, read_size); |
anhtran | 0:e9fd5575b10e | 185 | if (audio_data_size > 0) { |
anhtran | 0:e9fd5575b10e | 186 | if (padding_size != 0) { |
anhtran | 0:e9fd5575b10e | 187 | int idx_w = _audio_buff_size - 1; |
anhtran | 0:e9fd5575b10e | 188 | int idx_r = read_size - 1; |
anhtran | 0:e9fd5575b10e | 189 | uint32_t block_byte = (decoder->GetBlockSize() + 7) / 8; |
anhtran | 0:e9fd5575b10e | 190 | |
anhtran | 0:e9fd5575b10e | 191 | // fill the shortfall with 0 |
anhtran | 0:e9fd5575b10e | 192 | for (i = audio_data_size; i < read_size; i++) { |
anhtran | 0:e9fd5575b10e | 193 | p_buf[i] = 0; |
anhtran | 0:e9fd5575b10e | 194 | } |
anhtran | 0:e9fd5575b10e | 195 | |
anhtran | 0:e9fd5575b10e | 196 | while (idx_w >= 0) { |
anhtran | 0:e9fd5575b10e | 197 | // padding |
anhtran | 0:e9fd5575b10e | 198 | for (i = 0; i < padding_size; i++) { |
anhtran | 0:e9fd5575b10e | 199 | p_buf[idx_w--] = 0x00; |
anhtran | 0:e9fd5575b10e | 200 | } |
anhtran | 0:e9fd5575b10e | 201 | for (i = 0; i < block_byte; i++) { |
anhtran | 0:e9fd5575b10e | 202 | p_buf[idx_w--] = p_buf[idx_r--]; |
anhtran | 0:e9fd5575b10e | 203 | } |
anhtran | 0:e9fd5575b10e | 204 | } |
anhtran | 0:e9fd5575b10e | 205 | dcache_clean(p_buf, _audio_buff_size); |
anhtran | 0:e9fd5575b10e | 206 | _audio->write(p_buf, _audio_buff_size, &audio_write_async_ctl); |
anhtran | 0:e9fd5575b10e | 207 | } else { |
anhtran | 0:e9fd5575b10e | 208 | dcache_clean(p_buf, audio_data_size); |
anhtran | 0:e9fd5575b10e | 209 | _audio->write(p_buf, audio_data_size, &audio_write_async_ctl); |
anhtran | 0:e9fd5575b10e | 210 | } |
anhtran | 0:e9fd5575b10e | 211 | if ((_buff_index + 1) < _audio_write_buff_num) { |
anhtran | 0:e9fd5575b10e | 212 | _buff_index++; |
anhtran | 0:e9fd5575b10e | 213 | } else { |
anhtran | 0:e9fd5575b10e | 214 | _buff_index = 0; |
anhtran | 0:e9fd5575b10e | 215 | } |
anhtran | 0:e9fd5575b10e | 216 | } else { |
anhtran | 0:e9fd5575b10e | 217 | break; |
anhtran | 0:e9fd5575b10e | 218 | } |
anhtran | 0:e9fd5575b10e | 219 | } |
anhtran | 0:e9fd5575b10e | 220 | } |
anhtran | 0:e9fd5575b10e | 221 | ThisThread::sleep_for(500); |
anhtran | 0:e9fd5575b10e | 222 | ret = true; |
anhtran | 0:e9fd5575b10e | 223 | } |
anhtran | 0:e9fd5575b10e | 224 | delete decoder; |
anhtran | 0:e9fd5575b10e | 225 | if (fp != NULL) { |
anhtran | 0:e9fd5575b10e | 226 | fclose(fp); |
anhtran | 0:e9fd5575b10e | 227 | } |
anhtran | 0:e9fd5575b10e | 228 | |
anhtran | 0:e9fd5575b10e | 229 | return ret; |
anhtran | 0:e9fd5575b10e | 230 | } |
anhtran | 0:e9fd5575b10e | 231 | |
anhtran | 0:e9fd5575b10e | 232 | bool EasyPlayback::is_paused(void) |
anhtran | 0:e9fd5575b10e | 233 | { |
anhtran | 0:e9fd5575b10e | 234 | return _pause; |
anhtran | 0:e9fd5575b10e | 235 | } |
anhtran | 0:e9fd5575b10e | 236 | |
anhtran | 0:e9fd5575b10e | 237 | void EasyPlayback::pause() |
anhtran | 0:e9fd5575b10e | 238 | { |
anhtran | 0:e9fd5575b10e | 239 | _pause = !_pause; |
anhtran | 0:e9fd5575b10e | 240 | } |
anhtran | 0:e9fd5575b10e | 241 | |
anhtran | 0:e9fd5575b10e | 242 | void EasyPlayback::pause(bool type) |
anhtran | 0:e9fd5575b10e | 243 | { |
anhtran | 0:e9fd5575b10e | 244 | _pause = type; |
anhtran | 0:e9fd5575b10e | 245 | } |
anhtran | 0:e9fd5575b10e | 246 | |
anhtran | 0:e9fd5575b10e | 247 | void EasyPlayback::skip(void) |
anhtran | 0:e9fd5575b10e | 248 | { |
anhtran | 0:e9fd5575b10e | 249 | _skip = true; |
anhtran | 0:e9fd5575b10e | 250 | } |
anhtran | 0:e9fd5575b10e | 251 | |
anhtran | 0:e9fd5575b10e | 252 | bool EasyPlayback::outputVolume(float VolumeOut) |
anhtran | 0:e9fd5575b10e | 253 | { |
anhtran | 0:e9fd5575b10e | 254 | if (!_init_end) { |
anhtran | 0:e9fd5575b10e | 255 | _audio->power(); |
anhtran | 0:e9fd5575b10e | 256 | _init_end = true; |
anhtran | 0:e9fd5575b10e | 257 | } |
anhtran | 0:e9fd5575b10e | 258 | return _audio->outputVolume(VolumeOut, VolumeOut); |
anhtran | 0:e9fd5575b10e | 259 | } |
anhtran | 0:e9fd5575b10e | 260 | |
anhtran | 0:e9fd5575b10e | 261 | EasyDecoder * EasyPlayback::create_decoer_class(const char* filename) |
anhtran | 0:e9fd5575b10e | 262 | { |
anhtran | 0:e9fd5575b10e | 263 | std::map<std::string, EasyDecoder*(*)()>::iterator itr; |
anhtran | 0:e9fd5575b10e | 264 | char *extension = strstr((char *)filename, "."); |
anhtran | 0:e9fd5575b10e | 265 | |
anhtran | 0:e9fd5575b10e | 266 | if (extension == NULL) { |
anhtran | 0:e9fd5575b10e | 267 | return NULL; |
anhtran | 0:e9fd5575b10e | 268 | } |
anhtran | 0:e9fd5575b10e | 269 | |
anhtran | 0:e9fd5575b10e | 270 | itr = m_lpDecoders.find(extension); |
anhtran | 0:e9fd5575b10e | 271 | if (itr == m_lpDecoders.end()) { |
anhtran | 0:e9fd5575b10e | 272 | return NULL; |
anhtran | 0:e9fd5575b10e | 273 | } |
anhtran | 0:e9fd5575b10e | 274 | |
anhtran | 0:e9fd5575b10e | 275 | return (*itr).second(); |
anhtran | 0:e9fd5575b10e | 276 | } |
anhtran | 0:e9fd5575b10e | 277 |