Daiki Kato / EasyPlayback

Dependents:   GR-PEACH_Audio_WAV_PwmOut GR-Boards_Audio_WAV

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EasyPlayback.cpp Source File

EasyPlayback.cpp

00001 /* mbed EasyPlayback Library
00002  * Copyright (C) 2017 dkato
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "dcache-control.h"
00019 #include "EasyPlayback.h"
00020 
00021 EasyPlayback::EasyPlayback(audio_type_t type, PinName pin1, PinName pin2) : 
00022      _buff_index(0), _type(type), _skip(false), _pause(false), _init_end(false)
00023 {
00024     _audio_ssif = NULL;
00025     _audio_pwm = NULL;
00026     if (_type == AUDIO_TPYE_SSIF) {
00027         _audio_buff_size = 4096;
00028         _audio_ssif = new AUDIO_GRBoard(0x80, (AUDIO_WRITE_BUFF_NUM - 1), 0);
00029         _audio = _audio_ssif;
00030     } else if (_type == AUDIO_TPYE_PWM) {
00031         _audio_buff_size = 4096;
00032         _audio_pwm = new PwmOutSpeaker(pin1, pin2);
00033         _audio = _audio_pwm;
00034     } else if (_type == AUDIO_TPYE_SPDIF) {
00035         MBED_ASSERT(false);
00036     } else {
00037         MBED_ASSERT(false);
00038     }
00039     _heap_buf = new uint8_t[_audio_buff_size * AUDIO_WRITE_BUFF_NUM + 31];
00040     _audio_buf = (uint8_t *)(((uint32_t)_heap_buf + 31ul) & ~31ul);
00041 }
00042 
00043 EasyPlayback::~EasyPlayback()
00044 {
00045     if (_audio_ssif != NULL) {
00046         delete _audio_ssif;
00047     }
00048     if (_audio_pwm != NULL) {
00049         delete _audio_pwm;
00050     }
00051     delete [] _heap_buf;
00052 }
00053 
00054 bool EasyPlayback::get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size)
00055 {
00056     FILE * fp = NULL;
00057     EasyDecoder * decoder;
00058     bool ret = false;
00059 
00060     decoder = create_decoer_class(filename);
00061     if (decoder == NULL) {
00062         return false;
00063     }
00064 
00065     fp = fopen(filename, "r");
00066     if (fp == NULL) {
00067         // do nothing
00068     } else if (decoder->AnalyzeHeder(p_title, p_artist, p_album, tag_size, fp) != false) {
00069         ret = true;
00070     }
00071     delete decoder;
00072     if (fp != NULL) {
00073         fclose(fp);
00074     }
00075 
00076     return ret;
00077 }
00078 
00079 bool EasyPlayback::play(const char* filename)
00080 {
00081     const rbsp_data_conf_t audio_write_async_ctl = {NULL, NULL};
00082     size_t audio_data_size;
00083     FILE * fp = NULL;
00084     uint8_t * p_buf;
00085     uint32_t read_size;
00086     uint32_t i;
00087     EasyDecoder * decoder;
00088     bool ret = false;
00089     uint32_t padding_size;
00090 
00091     decoder = create_decoer_class(filename);
00092     if (decoder == NULL) {
00093         return false;
00094     }
00095 
00096     if (!_init_end) {
00097         _audio->power();
00098         _audio->outputVolume(1.0, 1.0);
00099         _init_end = true;
00100     }
00101 
00102      _skip = false;
00103     fp = fopen(filename, "r");
00104     if (fp == NULL) {
00105         // do nothing
00106     } else if (decoder->AnalyzeHeder(NULL, NULL, NULL, 0, fp) == false) {
00107         // do nothing
00108     } else if  ((decoder->GetChannel() != 2)
00109             || (_audio->format(decoder->GetBlockSize()) == false)
00110             || (_audio->frequency(decoder->GetSamplingRate()) == false)) {
00111         // do nothing
00112     } else {
00113         if ((_type == AUDIO_TPYE_SPDIF) && (decoder->GetBlockSize() == 16)) {
00114             padding_size = 2;
00115             read_size = _audio_buff_size / 2;
00116         } else if ((decoder->GetBlockSize() == 20) || (decoder->GetBlockSize() == 24)) {
00117             padding_size = 1;
00118             read_size = _audio_buff_size * 3 / 4;
00119         } else {
00120             padding_size = 0;
00121             read_size = _audio_buff_size;
00122         }
00123         setvbuf(fp, NULL, _IONBF, 0); // unbuffered
00124 
00125         while (true) {
00126             while ((_pause) && (!_skip)) {
00127                 Thread::wait(100);
00128             }
00129             if (_skip) {
00130                 break;
00131             }
00132             p_buf = &_audio_buf[_audio_buff_size * _buff_index];
00133             audio_data_size = decoder->GetNextData(p_buf, read_size);
00134             if (audio_data_size > 0) {
00135                 if (padding_size != 0) {
00136                     int idx_w = _audio_buff_size - 1;
00137                     int idx_r = read_size - 1;
00138                     uint32_t block_byte = (decoder->GetBlockSize() + 7) / 8;
00139 
00140                     // fill the shortfall with 0
00141                     for (i = audio_data_size; i < read_size; i++) {
00142                         p_buf[i] = 0;
00143                     }
00144 
00145                     while (idx_w >= 0) {
00146                         // padding
00147                         for (i = 0; i < padding_size; i++) {
00148                             p_buf[idx_w--] = 0x00;
00149                         }
00150                         for (i = 0; i < block_byte; i++) {
00151                             p_buf[idx_w--] = p_buf[idx_r--];
00152                         }
00153                     }
00154                     dcache_clean(p_buf, _audio_buff_size);
00155                     _audio->write(p_buf, _audio_buff_size, &audio_write_async_ctl);
00156                 } else {
00157                     dcache_clean(p_buf, audio_data_size);
00158                     _audio->write(p_buf, audio_data_size, &audio_write_async_ctl);
00159                 }
00160                 _buff_index = (_buff_index + 1) & AUDIO_MSK_RING_BUFF;
00161             } else {
00162                 break;
00163             }
00164         }
00165         Thread::wait(500);
00166         ret = true;
00167     }
00168     delete decoder;
00169     if (fp != NULL) {
00170         fclose(fp);
00171     }
00172 
00173     return ret;
00174 }
00175 
00176 bool EasyPlayback::is_paused(void)
00177 {
00178     return _pause;
00179 }
00180 
00181 void EasyPlayback::pause()
00182 {
00183     _pause = !_pause;
00184 }
00185 
00186 void EasyPlayback::pause(bool type)
00187 {
00188     _pause = type;
00189 }
00190 
00191 void EasyPlayback::skip(void)
00192 {
00193     _skip = true;
00194 }
00195 
00196 bool EasyPlayback::outputVolume(float VolumeOut)
00197 {
00198     if (!_init_end) {
00199         _audio->power();
00200         _init_end = true;
00201     }
00202     return _audio->outputVolume(VolumeOut, VolumeOut);
00203 }
00204 
00205 EasyDecoder * EasyPlayback::create_decoer_class(const char* filename)
00206 {
00207     std::map<std::string, EasyDecoder*(*)()>::iterator itr;
00208     char *extension = strstr((char *)filename, ".");
00209 
00210     if (extension == NULL) {
00211         return NULL;
00212     }
00213 
00214     itr = m_lpDecoders.find(extension);
00215     if (itr == m_lpDecoders.end()) {
00216         return NULL;
00217     }
00218 
00219     return (*itr).second();
00220 }
00221