![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
test public
Dependencies: HttpServer_snapshot_mbed-os
Diff: mbed-gr-libs/EasyPlayback/EasyPlayback.cpp
- Revision:
- 0:e9fd5575b10e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-gr-libs/EasyPlayback/EasyPlayback.cpp Fri Oct 18 03:09:43 2019 +0000 @@ -0,0 +1,277 @@ +/* mbed EasyPlayback Library + * Copyright (C) 2017 dkato + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "dcache-control.h" +#include "EasyPlayback.h" + +EasyPlayback::EasyPlayback(audio_type_t type, PinName pin1, PinName pin2) : + _buff_index(0), _type(type), _skip(false), _pause(false), _init_end(false) +{ + _audio_buff_size = 0; + _audio_write_buff_num = 0; + _audio_ssif = NULL; + _audio_pwm = NULL; +#if (R_BSP_SPDIF_ENABLE == 1) + _audio_spdif = NULL; +#endif + _audio_soundless = NULL; + _heap_buf = NULL; + _audio_buf = NULL; + if (_type == AUDIO_TPYE_SSIF) { + _audio_buff_size = 4096; + _audio_write_buff_num = 8; + _audio_ssif = new AUDIO_GRBoard(0x80, (_audio_write_buff_num - 1), 0); + _audio = _audio_ssif; + } else if (_type == AUDIO_TPYE_PWM) { + _audio_buff_size = 4096; + _audio_write_buff_num = 8; + _audio_pwm = new PwmOutSpeaker(pin1, pin2); + _audio = _audio_pwm; + } else if (_type == AUDIO_TPYE_SPDIF) { +#if (R_BSP_SPDIF_ENABLE == 1) + _audio_buff_size = (192 * 2 * 10); + _audio_write_buff_num = 8; + _audio_spdif = new SPDIF_GRBoard(0x80, (_audio_write_buff_num - 1), 0); + _audio = _audio_spdif; +#else + MBED_ASSERT(false); +#endif + } else if (_type == AUDIO_TPYE_SOUNDLESS) { + _audio_buff_size = (4410 * 2); + _audio_write_buff_num = 0; + _audio_soundless = new SoundlessSpeaker(); + _audio = _audio_soundless; + } else if (_type == AUDIO_TPYE_NULL) { + _audio_buff_size = 4096; + _audio_write_buff_num = 0; + _audio_null = new NullSpeaker(); + _audio = _audio_null; + } else { + MBED_ASSERT(false); + } + if ((_audio_buff_size != 0) && (_audio_write_buff_num != 0)) { + _heap_buf = new uint8_t[_audio_buff_size * _audio_write_buff_num + 31]; + _audio_buf = (uint8_t *)(((uint32_t)_heap_buf + 31ul) & ~31ul); + } +} + +EasyPlayback::~EasyPlayback() +{ + if (_audio_ssif != NULL) { + delete _audio_ssif; + } + if (_audio_pwm != NULL) { + delete _audio_pwm; + } +#if (R_BSP_SPDIF_ENABLE == 1) + if (_audio_spdif != NULL) { + delete _audio_spdif; + } +#endif + if (_audio_soundless != NULL) { + delete _audio_soundless; + } + if (_heap_buf != NULL) { + delete [] _heap_buf; + } +} + +bool EasyPlayback::get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size) +{ + FILE * fp = NULL; + EasyDecoder * decoder; + bool ret = false; + + decoder = create_decoer_class(filename); + if (decoder == NULL) { + return false; + } + + fp = fopen(filename, "r"); + if (fp == NULL) { + // do nothing + } else if (decoder->AnalyzeHeder(p_title, p_artist, p_album, tag_size, fp) != false) { + ret = true; + } + delete decoder; + if (fp != NULL) { + fclose(fp); + } + + return ret; +} + +bool EasyPlayback::play(const char* filename) +{ + const rbsp_data_conf_t audio_write_async_ctl = {NULL, NULL}; + size_t audio_data_size; + FILE * fp = NULL; + uint8_t * p_buf; + uint32_t read_size; + uint32_t i; + EasyDecoder * decoder; + bool ret = false; + uint32_t padding_size; + + decoder = create_decoer_class(filename); + if (decoder == NULL) { + return false; + } + + if (!_init_end) { + _audio->power(); + _audio->outputVolume(1.0, 1.0); + _init_end = true; + } + + _skip = false; + fp = fopen(filename, "r"); + if (fp == NULL) { + // do nothing + } else if (decoder->AnalyzeHeder(NULL, NULL, NULL, 0, fp) == false) { + // do nothing + } else if ((decoder->GetChannel() != 2) + || (_audio->format(decoder->GetBlockSize()) == false) + || (_audio->frequency(decoder->GetSamplingRate()) == false)) { + // do nothing + } else { + if ((_type == AUDIO_TPYE_SPDIF) && (decoder->GetBlockSize() == 16)) { + padding_size = 2; + read_size = _audio_buff_size / 2; + } else if ((decoder->GetBlockSize() == 20) || (decoder->GetBlockSize() == 24)) { + padding_size = 1; + read_size = _audio_buff_size * 3 / 4; + } else { + padding_size = 0; + read_size = _audio_buff_size; + } + setvbuf(fp, NULL, _IONBF, 0); // unbuffered + + while (true) { + while ((_pause) && (!_skip)) { + ThisThread::sleep_for(100); + } + if (_skip) { + break; + } + if (_audio_buf == NULL) { + audio_data_size = decoder->GetNextData(NULL, read_size); + if (audio_data_size > 0) { + if (padding_size != 0) { + _audio->write(NULL, _audio_buff_size, &audio_write_async_ctl); + } else { + _audio->write(NULL, audio_data_size, &audio_write_async_ctl); + } + } else { + break; + } + } else { + p_buf = &_audio_buf[_audio_buff_size * _buff_index]; + audio_data_size = decoder->GetNextData(p_buf, read_size); + if (audio_data_size > 0) { + if (padding_size != 0) { + int idx_w = _audio_buff_size - 1; + int idx_r = read_size - 1; + uint32_t block_byte = (decoder->GetBlockSize() + 7) / 8; + + // fill the shortfall with 0 + for (i = audio_data_size; i < read_size; i++) { + p_buf[i] = 0; + } + + while (idx_w >= 0) { + // padding + for (i = 0; i < padding_size; i++) { + p_buf[idx_w--] = 0x00; + } + for (i = 0; i < block_byte; i++) { + p_buf[idx_w--] = p_buf[idx_r--]; + } + } + dcache_clean(p_buf, _audio_buff_size); + _audio->write(p_buf, _audio_buff_size, &audio_write_async_ctl); + } else { + dcache_clean(p_buf, audio_data_size); + _audio->write(p_buf, audio_data_size, &audio_write_async_ctl); + } + if ((_buff_index + 1) < _audio_write_buff_num) { + _buff_index++; + } else { + _buff_index = 0; + } + } else { + break; + } + } + } + ThisThread::sleep_for(500); + ret = true; + } + delete decoder; + if (fp != NULL) { + fclose(fp); + } + + return ret; +} + +bool EasyPlayback::is_paused(void) +{ + return _pause; +} + +void EasyPlayback::pause() +{ + _pause = !_pause; +} + +void EasyPlayback::pause(bool type) +{ + _pause = type; +} + +void EasyPlayback::skip(void) +{ + _skip = true; +} + +bool EasyPlayback::outputVolume(float VolumeOut) +{ + if (!_init_end) { + _audio->power(); + _init_end = true; + } + return _audio->outputVolume(VolumeOut, VolumeOut); +} + +EasyDecoder * EasyPlayback::create_decoer_class(const char* filename) +{ + std::map<std::string, EasyDecoder*(*)()>::iterator itr; + char *extension = strstr((char *)filename, "."); + + if (extension == NULL) { + return NULL; + } + + itr = m_lpDecoders.find(extension); + if (itr == m_lpDecoders.end()) { + return NULL; + } + + return (*itr).second(); +} +