Easy playback library for AUDIO_GRBoard.

Dependents:   GR-PEACH_Audio_WAV_PwmOut GR-Boards_Audio_WAV

Committer:
dkato
Date:
Tue Jul 24 08:45:30 2018 +0000
Revision:
2:6c46c61630b3
Parent:
1:fdd79b99ba73
Add PwmOutSpeaker to output

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:9956e2ed09da 1 /* mbed EasyPlayback Library
dkato 0:9956e2ed09da 2 * Copyright (C) 2017 dkato
dkato 0:9956e2ed09da 3 *
dkato 0:9956e2ed09da 4 * Licensed under the Apache License, Version 2.0 (the "License");
dkato 0:9956e2ed09da 5 * you may not use this file except in compliance with the License.
dkato 0:9956e2ed09da 6 * You may obtain a copy of the License at
dkato 0:9956e2ed09da 7 *
dkato 0:9956e2ed09da 8 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:9956e2ed09da 9 *
dkato 0:9956e2ed09da 10 * Unless required by applicable law or agreed to in writing, software
dkato 0:9956e2ed09da 11 * distributed under the License is distributed on an "AS IS" BASIS,
dkato 0:9956e2ed09da 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:9956e2ed09da 13 * See the License for the specific language governing permissions and
dkato 0:9956e2ed09da 14 * limitations under the License.
dkato 0:9956e2ed09da 15 */
dkato 0:9956e2ed09da 16
dkato 0:9956e2ed09da 17 #include "mbed.h"
dkato 0:9956e2ed09da 18 #include "dcache-control.h"
dkato 0:9956e2ed09da 19 #include "EasyPlayback.h"
dkato 0:9956e2ed09da 20
dkato 2:6c46c61630b3 21 EasyPlayback::EasyPlayback(audio_type_t type, PinName pin1, PinName pin2) :
dkato 1:fdd79b99ba73 22 _buff_index(0), _type(type), _skip(false), _pause(false), _init_end(false)
dkato 0:9956e2ed09da 23 {
dkato 1:fdd79b99ba73 24 _audio_ssif = NULL;
dkato 2:6c46c61630b3 25 _audio_pwm = NULL;
dkato 1:fdd79b99ba73 26 if (_type == AUDIO_TPYE_SSIF) {
dkato 1:fdd79b99ba73 27 _audio_buff_size = 4096;
dkato 1:fdd79b99ba73 28 _audio_ssif = new AUDIO_GRBoard(0x80, (AUDIO_WRITE_BUFF_NUM - 1), 0);
dkato 1:fdd79b99ba73 29 _audio = _audio_ssif;
dkato 2:6c46c61630b3 30 } else if (_type == AUDIO_TPYE_PWM) {
dkato 2:6c46c61630b3 31 _audio_buff_size = 4096;
dkato 2:6c46c61630b3 32 _audio_pwm = new PwmOutSpeaker(pin1, pin2);
dkato 2:6c46c61630b3 33 _audio = _audio_pwm;
dkato 1:fdd79b99ba73 34 } else if (_type == AUDIO_TPYE_SPDIF) {
dkato 1:fdd79b99ba73 35 MBED_ASSERT(false);
dkato 1:fdd79b99ba73 36 } else {
dkato 1:fdd79b99ba73 37 MBED_ASSERT(false);
dkato 1:fdd79b99ba73 38 }
dkato 1:fdd79b99ba73 39 _heap_buf = new uint8_t[_audio_buff_size * AUDIO_WRITE_BUFF_NUM + 31];
dkato 1:fdd79b99ba73 40 _audio_buf = (uint8_t *)(((uint32_t)_heap_buf + 31ul) & ~31ul);
dkato 0:9956e2ed09da 41 }
dkato 0:9956e2ed09da 42
dkato 0:9956e2ed09da 43 EasyPlayback::~EasyPlayback()
dkato 0:9956e2ed09da 44 {
dkato 1:fdd79b99ba73 45 if (_audio_ssif != NULL) {
dkato 1:fdd79b99ba73 46 delete _audio_ssif;
dkato 1:fdd79b99ba73 47 }
dkato 2:6c46c61630b3 48 if (_audio_pwm != NULL) {
dkato 2:6c46c61630b3 49 delete _audio_pwm;
dkato 1:fdd79b99ba73 50 }
dkato 0:9956e2ed09da 51 delete [] _heap_buf;
dkato 0:9956e2ed09da 52 }
dkato 0:9956e2ed09da 53
dkato 0:9956e2ed09da 54 bool EasyPlayback::get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size)
dkato 0:9956e2ed09da 55 {
dkato 1:fdd79b99ba73 56 FILE * fp = NULL;
dkato 0:9956e2ed09da 57 EasyDecoder * decoder;
dkato 0:9956e2ed09da 58 bool ret = false;
dkato 0:9956e2ed09da 59
dkato 0:9956e2ed09da 60 decoder = create_decoer_class(filename);
dkato 0:9956e2ed09da 61 if (decoder == NULL) {
dkato 0:9956e2ed09da 62 return false;
dkato 0:9956e2ed09da 63 }
dkato 0:9956e2ed09da 64
dkato 0:9956e2ed09da 65 fp = fopen(filename, "r");
dkato 1:fdd79b99ba73 66 if (fp == NULL) {
dkato 1:fdd79b99ba73 67 // do nothing
dkato 1:fdd79b99ba73 68 } else if (decoder->AnalyzeHeder(p_title, p_artist, p_album, tag_size, fp) != false) {
dkato 0:9956e2ed09da 69 ret = true;
dkato 0:9956e2ed09da 70 }
dkato 0:9956e2ed09da 71 delete decoder;
dkato 1:fdd79b99ba73 72 if (fp != NULL) {
dkato 1:fdd79b99ba73 73 fclose(fp);
dkato 1:fdd79b99ba73 74 }
dkato 0:9956e2ed09da 75
dkato 0:9956e2ed09da 76 return ret;
dkato 0:9956e2ed09da 77 }
dkato 0:9956e2ed09da 78
dkato 0:9956e2ed09da 79 bool EasyPlayback::play(const char* filename)
dkato 0:9956e2ed09da 80 {
dkato 0:9956e2ed09da 81 const rbsp_data_conf_t audio_write_async_ctl = {NULL, NULL};
dkato 1:fdd79b99ba73 82 size_t audio_data_size;
dkato 1:fdd79b99ba73 83 FILE * fp = NULL;
dkato 0:9956e2ed09da 84 uint8_t * p_buf;
dkato 1:fdd79b99ba73 85 uint32_t read_size;
dkato 1:fdd79b99ba73 86 uint32_t i;
dkato 0:9956e2ed09da 87 EasyDecoder * decoder;
dkato 0:9956e2ed09da 88 bool ret = false;
dkato 1:fdd79b99ba73 89 uint32_t padding_size;
dkato 0:9956e2ed09da 90
dkato 0:9956e2ed09da 91 decoder = create_decoer_class(filename);
dkato 0:9956e2ed09da 92 if (decoder == NULL) {
dkato 0:9956e2ed09da 93 return false;
dkato 0:9956e2ed09da 94 }
dkato 0:9956e2ed09da 95
dkato 0:9956e2ed09da 96 if (!_init_end) {
dkato 1:fdd79b99ba73 97 _audio->power();
dkato 1:fdd79b99ba73 98 _audio->outputVolume(1.0, 1.0);
dkato 0:9956e2ed09da 99 _init_end = true;
dkato 0:9956e2ed09da 100 }
dkato 0:9956e2ed09da 101
dkato 0:9956e2ed09da 102 _skip = false;
dkato 0:9956e2ed09da 103 fp = fopen(filename, "r");
dkato 1:fdd79b99ba73 104 if (fp == NULL) {
dkato 1:fdd79b99ba73 105 // do nothing
dkato 1:fdd79b99ba73 106 } else if (decoder->AnalyzeHeder(NULL, NULL, NULL, 0, fp) == false) {
dkato 0:9956e2ed09da 107 // do nothing
dkato 0:9956e2ed09da 108 } else if ((decoder->GetChannel() != 2)
dkato 1:fdd79b99ba73 109 || (_audio->format(decoder->GetBlockSize()) == false)
dkato 1:fdd79b99ba73 110 || (_audio->frequency(decoder->GetSamplingRate()) == false)) {
dkato 0:9956e2ed09da 111 // do nothing
dkato 0:9956e2ed09da 112 } else {
dkato 1:fdd79b99ba73 113 if ((_type == AUDIO_TPYE_SPDIF) && (decoder->GetBlockSize() == 16)) {
dkato 1:fdd79b99ba73 114 padding_size = 2;
dkato 1:fdd79b99ba73 115 read_size = _audio_buff_size / 2;
dkato 1:fdd79b99ba73 116 } else if ((decoder->GetBlockSize() == 20) || (decoder->GetBlockSize() == 24)) {
dkato 1:fdd79b99ba73 117 padding_size = 1;
dkato 1:fdd79b99ba73 118 read_size = _audio_buff_size * 3 / 4;
dkato 1:fdd79b99ba73 119 } else {
dkato 1:fdd79b99ba73 120 padding_size = 0;
dkato 1:fdd79b99ba73 121 read_size = _audio_buff_size;
dkato 1:fdd79b99ba73 122 }
dkato 1:fdd79b99ba73 123 setvbuf(fp, NULL, _IONBF, 0); // unbuffered
dkato 1:fdd79b99ba73 124
dkato 1:fdd79b99ba73 125 while (true) {
dkato 0:9956e2ed09da 126 while ((_pause) && (!_skip)) {
dkato 0:9956e2ed09da 127 Thread::wait(100);
dkato 0:9956e2ed09da 128 }
dkato 0:9956e2ed09da 129 if (_skip) {
dkato 0:9956e2ed09da 130 break;
dkato 0:9956e2ed09da 131 }
dkato 1:fdd79b99ba73 132 p_buf = &_audio_buf[_audio_buff_size * _buff_index];
dkato 1:fdd79b99ba73 133 audio_data_size = decoder->GetNextData(p_buf, read_size);
dkato 0:9956e2ed09da 134 if (audio_data_size > 0) {
dkato 1:fdd79b99ba73 135 if (padding_size != 0) {
dkato 1:fdd79b99ba73 136 int idx_w = _audio_buff_size - 1;
dkato 1:fdd79b99ba73 137 int idx_r = read_size - 1;
dkato 1:fdd79b99ba73 138 uint32_t block_byte = (decoder->GetBlockSize() + 7) / 8;
dkato 1:fdd79b99ba73 139
dkato 1:fdd79b99ba73 140 // fill the shortfall with 0
dkato 1:fdd79b99ba73 141 for (i = audio_data_size; i < read_size; i++) {
dkato 1:fdd79b99ba73 142 p_buf[i] = 0;
dkato 1:fdd79b99ba73 143 }
dkato 1:fdd79b99ba73 144
dkato 1:fdd79b99ba73 145 while (idx_w >= 0) {
dkato 1:fdd79b99ba73 146 // padding
dkato 1:fdd79b99ba73 147 for (i = 0; i < padding_size; i++) {
dkato 1:fdd79b99ba73 148 p_buf[idx_w--] = 0x00;
dkato 1:fdd79b99ba73 149 }
dkato 1:fdd79b99ba73 150 for (i = 0; i < block_byte; i++) {
dkato 1:fdd79b99ba73 151 p_buf[idx_w--] = p_buf[idx_r--];
dkato 1:fdd79b99ba73 152 }
dkato 1:fdd79b99ba73 153 }
dkato 1:fdd79b99ba73 154 dcache_clean(p_buf, _audio_buff_size);
dkato 1:fdd79b99ba73 155 _audio->write(p_buf, _audio_buff_size, &audio_write_async_ctl);
dkato 1:fdd79b99ba73 156 } else {
dkato 1:fdd79b99ba73 157 dcache_clean(p_buf, audio_data_size);
dkato 1:fdd79b99ba73 158 _audio->write(p_buf, audio_data_size, &audio_write_async_ctl);
dkato 1:fdd79b99ba73 159 }
dkato 0:9956e2ed09da 160 _buff_index = (_buff_index + 1) & AUDIO_MSK_RING_BUFF;
dkato 1:fdd79b99ba73 161 } else {
dkato 1:fdd79b99ba73 162 break;
dkato 0:9956e2ed09da 163 }
dkato 0:9956e2ed09da 164 }
dkato 0:9956e2ed09da 165 Thread::wait(500);
dkato 0:9956e2ed09da 166 ret = true;
dkato 0:9956e2ed09da 167 }
dkato 0:9956e2ed09da 168 delete decoder;
dkato 1:fdd79b99ba73 169 if (fp != NULL) {
dkato 1:fdd79b99ba73 170 fclose(fp);
dkato 1:fdd79b99ba73 171 }
dkato 0:9956e2ed09da 172
dkato 0:9956e2ed09da 173 return ret;
dkato 0:9956e2ed09da 174 }
dkato 0:9956e2ed09da 175
dkato 0:9956e2ed09da 176 bool EasyPlayback::is_paused(void)
dkato 0:9956e2ed09da 177 {
dkato 0:9956e2ed09da 178 return _pause;
dkato 0:9956e2ed09da 179 }
dkato 0:9956e2ed09da 180
dkato 0:9956e2ed09da 181 void EasyPlayback::pause()
dkato 0:9956e2ed09da 182 {
dkato 0:9956e2ed09da 183 _pause = !_pause;
dkato 0:9956e2ed09da 184 }
dkato 0:9956e2ed09da 185
dkato 0:9956e2ed09da 186 void EasyPlayback::pause(bool type)
dkato 0:9956e2ed09da 187 {
dkato 0:9956e2ed09da 188 _pause = type;
dkato 0:9956e2ed09da 189 }
dkato 0:9956e2ed09da 190
dkato 0:9956e2ed09da 191 void EasyPlayback::skip(void)
dkato 0:9956e2ed09da 192 {
dkato 0:9956e2ed09da 193 _skip = true;
dkato 0:9956e2ed09da 194 }
dkato 0:9956e2ed09da 195
dkato 0:9956e2ed09da 196 bool EasyPlayback::outputVolume(float VolumeOut)
dkato 0:9956e2ed09da 197 {
dkato 0:9956e2ed09da 198 if (!_init_end) {
dkato 1:fdd79b99ba73 199 _audio->power();
dkato 0:9956e2ed09da 200 _init_end = true;
dkato 0:9956e2ed09da 201 }
dkato 1:fdd79b99ba73 202 return _audio->outputVolume(VolumeOut, VolumeOut);
dkato 0:9956e2ed09da 203 }
dkato 0:9956e2ed09da 204
dkato 0:9956e2ed09da 205 EasyDecoder * EasyPlayback::create_decoer_class(const char* filename)
dkato 0:9956e2ed09da 206 {
dkato 0:9956e2ed09da 207 std::map<std::string, EasyDecoder*(*)()>::iterator itr;
dkato 0:9956e2ed09da 208 char *extension = strstr((char *)filename, ".");
dkato 0:9956e2ed09da 209
dkato 0:9956e2ed09da 210 if (extension == NULL) {
dkato 0:9956e2ed09da 211 return NULL;
dkato 0:9956e2ed09da 212 }
dkato 0:9956e2ed09da 213
dkato 0:9956e2ed09da 214 itr = m_lpDecoders.find(extension);
dkato 0:9956e2ed09da 215 if (itr == m_lpDecoders.end()) {
dkato 0:9956e2ed09da 216 return NULL;
dkato 0:9956e2ed09da 217 }
dkato 0:9956e2ed09da 218
dkato 0:9956e2ed09da 219 return (*itr).second();
dkato 0:9956e2ed09da 220 }
dkato 0:9956e2ed09da 221