yoshi matsu / EasyPlayback
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) : 
00022      _buff_index(0), _type(type), _skip(false), _pause(false), _init_end(false)
00023 {
00024     _audio_ssif = NULL;
00025     if (_type == AUDIO_TPYE_SSIF) {
00026         _audio_buff_size = 4096;
00027         _audio_ssif = new AUDIO_GRBoard(0x80, (AUDIO_WRITE_BUFF_NUM - 1), 0);
00028     } else if (_type == AUDIO_TPYE_SPDIF) {
00029         MBED_ASSERT(false);
00030     } else {
00031         MBED_ASSERT(false);
00032     }
00033     _heap_buf = new uint8_t[_audio_buff_size * AUDIO_WRITE_BUFF_NUM + 31];
00034     _audio_buf = (uint8_t *)(((uint32_t)_heap_buf + 31ul) & ~31ul);
00035 }
00036 
00037 EasyPlayback::~EasyPlayback()
00038 {
00039     if (_audio_ssif != NULL) {
00040         delete _audio_ssif;
00041     }
00042 #if (R_BSP_SPDIF_ENABLE == 1)
00043     if (_audio_spdif != NULL) {
00044         delete _audio_spdif;
00045     }
00046 #endif
00047     delete [] _heap_buf;
00048 }
00049 
00050 bool EasyPlayback::get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size)
00051 {
00052     FILE * fp = NULL;
00053     EasyDecoder * decoder;
00054     bool ret = false;
00055 
00056     decoder = create_decoer_class(filename);
00057     if (decoder == NULL) {
00058         return false;
00059     }
00060 
00061     fp = fopen(filename, "r");
00062     if (fp == NULL) {
00063         // do nothing
00064     } else if (decoder->AnalyzeHeder(p_title, p_artist, p_album, tag_size, fp) != false) {
00065         ret = true;
00066     }
00067     delete decoder;
00068     if (fp != NULL) {
00069         fclose(fp);
00070     }
00071 
00072     return ret;
00073 }
00074 
00075 bool EasyPlayback::play(const char* filename)
00076 {
00077     const rbsp_data_conf_t audio_write_async_ctl = {NULL, NULL};
00078     size_t audio_data_size;
00079     FILE * fp = NULL;
00080     uint8_t * p_buf;
00081     uint32_t read_size;
00082     uint32_t i;
00083     EasyDecoder * decoder;
00084     bool ret = false;
00085     uint32_t padding_size;
00086 
00087     decoder = create_decoer_class(filename);
00088     if (decoder == NULL) {
00089         return false;
00090     }
00091 
00092     if (!_init_end) {
00093         _audio_ssif->power();
00094         _audio_ssif->outputVolume(1.0, 1.0);
00095         _init_end = true;
00096     }
00097 
00098      _skip = false;
00099     fp = fopen(filename, "r");
00100     if (fp == NULL) {
00101         // do nothing
00102     } else if (decoder->AnalyzeHeder(NULL, NULL, NULL, 0, fp) == false) {
00103         // do nothing
00104     } else if  ((decoder->GetChannel() != 2)
00105             || (_audio->format(decoder->GetBlockSize()) == false)
00106             || (_audio->frequency(decoder->GetSamplingRate()) == false)) {
00107         // do nothing
00108     } else {
00109         if ((_type == AUDIO_TPYE_SPDIF) && (decoder->GetBlockSize() == 16)) {
00110             padding_size = 2;
00111             read_size = _audio_buff_size / 2;
00112         } else if ((decoder->GetBlockSize() == 20) || (decoder->GetBlockSize() == 24)) {
00113             padding_size = 1;
00114             read_size = _audio_buff_size * 3 / 4;
00115         } else {
00116             padding_size = 0;
00117             read_size = _audio_buff_size;
00118         }
00119         setvbuf(fp, NULL, _IONBF, 0); // unbuffered
00120 
00121         while (true) {
00122             while ((_pause) && (!_skip)) {
00123                 Thread::wait(100);
00124             }
00125             if (_skip) {
00126                 break;
00127             }
00128             p_buf = &_audio_buf[_audio_buff_size * _buff_index];
00129             audio_data_size = decoder->GetNextData(p_buf, read_size);
00130             if (audio_data_size > 0) {
00131                 if (padding_size != 0) {
00132                     int idx_w = _audio_buff_size - 1;
00133                     int idx_r = read_size - 1;
00134                     uint32_t block_byte = (decoder->GetBlockSize() + 7) / 8;
00135 
00136                     // fill the shortfall with 0
00137                     for (i = audio_data_size; i < read_size; i++) {
00138                         p_buf[i] = 0;
00139                     }
00140 
00141                     while (idx_w >= 0) {
00142                         // padding
00143                         for (i = 0; i < padding_size; i++) {
00144                             p_buf[idx_w--] = 0x00;
00145                         }
00146                         for (i = 0; i < block_byte; i++) {
00147                             p_buf[idx_w--] = p_buf[idx_r--];
00148                         }
00149                     }
00150                     dcache_clean(p_buf, _audio_buff_size);
00151                     _audio->write(p_buf, _audio_buff_size, &audio_write_async_ctl);
00152                 } else {
00153                     dcache_clean(p_buf, audio_data_size);
00154                     _audio->write(p_buf, audio_data_size, &audio_write_async_ctl);
00155                 }
00156                 _buff_index = (_buff_index + 1) & AUDIO_MSK_RING_BUFF;
00157             } else {
00158                 break;
00159             }
00160         }
00161         Thread::wait(500);
00162         ret = true;
00163     }
00164     delete decoder;
00165     if (fp != NULL) {
00166         fclose(fp);
00167     }
00168 
00169     return ret;
00170 }
00171 
00172 bool EasyPlayback::is_paused(void)
00173 {
00174     return _pause;
00175 }
00176 
00177 void EasyPlayback::pause()
00178 {
00179     _pause = !_pause;
00180 }
00181 
00182 void EasyPlayback::pause(bool type)
00183 {
00184     _pause = type;
00185 }
00186 
00187 void EasyPlayback::skip(void)
00188 {
00189     _skip = true;
00190 }
00191 
00192 bool EasyPlayback::outputVolume(float VolumeOut)
00193 {
00194     if (!_init_end) {
00195         _audio->power();
00196         _init_end = true;
00197     }
00198     return _audio->outputVolume(VolumeOut, VolumeOut);
00199 }
00200 
00201 EasyDecoder * EasyPlayback::create_decoer_class(const char* filename)
00202 {
00203     std::map<std::string, EasyDecoder*(*)()>::iterator itr;
00204     char *extension = strstr((char *)filename, ".");
00205 
00206     if (extension == NULL) {
00207         return NULL;
00208     }
00209 
00210     itr = m_lpDecoders.find(extension);
00211     if (itr == m_lpDecoders.end()) {
00212         return NULL;
00213     }
00214 
00215     return (*itr).second();
00216 }
00217