Easy playback library for AUDIO_GRBoard.
Dependents: GR-PEACH_Audio_WAV_PwmOut GR-Boards_Audio_WAV
EasyPlayback.cpp
- Committer:
- dkato
- Date:
- 2018-07-24
- Revision:
- 2:6c46c61630b3
- Parent:
- 1:fdd79b99ba73
File content as of revision 2:6c46c61630b3:
/* 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_ssif = NULL; _audio_pwm = NULL; if (_type == AUDIO_TPYE_SSIF) { _audio_buff_size = 4096; _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_pwm = new PwmOutSpeaker(pin1, pin2); _audio = _audio_pwm; } else if (_type == AUDIO_TPYE_SPDIF) { MBED_ASSERT(false); } else { MBED_ASSERT(false); } _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; } 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)) { Thread::wait(100); } if (_skip) { break; } 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); } _buff_index = (_buff_index + 1) & AUDIO_MSK_RING_BUFF; } else { break; } } Thread::wait(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(); }