Easy playback library for PwmOutSpeaker.

Files at this revision

API Documentation at this revision

Comitter:
dkato
Date:
Thu Jul 06 04:42:29 2017 +0000
Commit message:
first commit

Changed in this revision

EasyPlaybackPWM.cpp Show annotated file Show diff for this revision Revisions of this file
EasyPlaybackPWM.h Show annotated file Show diff for this revision Revisions of this file
decoder/EasyDec_Wav.h Show annotated file Show diff for this revision Revisions of this file
decoder/EasyDec_WavCnv2ch.h Show annotated file Show diff for this revision Revisions of this file
decoder/EasyDecoder.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 41ab76b22961 EasyPlaybackPWM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EasyPlaybackPWM.cpp	Thu Jul 06 04:42:29 2017 +0000
@@ -0,0 +1,134 @@
+/* mbed EasyPlaybackPWM 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 "EasyPlaybackPWM.h"
+
+EasyPlaybackPWM::EasyPlaybackPWM(PinName pwm_l, PinName pwm_r) : audio(pwm_l, pwm_r), _skip(false), _pause(false)
+{
+    _audio_buf = new uint8_t[AUDIO_WRITE_BUFF_SIZE];
+}
+
+EasyPlaybackPWM::~EasyPlaybackPWM()
+{
+    delete [] _audio_buf;
+}
+
+bool EasyPlaybackPWM::get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size)
+{
+    FILE * fp;
+    EasyDecoder * decoder;
+    bool ret = false;
+
+    decoder = create_decoer_class(filename);
+    if (decoder == NULL) {
+        return false;
+    }
+
+    fp = fopen(filename, "r");
+    if (decoder->AnalyzeHeder(p_title, p_artist, p_album, tag_size, fp) != false) {
+        ret = true;
+    }
+    delete decoder;
+    fclose(fp);
+
+    return ret;
+}
+
+bool EasyPlaybackPWM::play(const char* filename)
+{
+    size_t audio_data_size = AUDIO_WRITE_BUFF_SIZE;
+    FILE * fp;
+    EasyDecoder * decoder;
+    bool ret = false;
+
+    decoder = create_decoer_class(filename);
+    if (decoder == NULL) {
+        return false;
+    }
+
+     _skip = false;
+    fp = fopen(filename, "r");
+    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 {
+        while (audio_data_size == AUDIO_WRITE_BUFF_SIZE) {
+            while ((_pause) && (!_skip)) {
+                Thread::wait(100);
+            }
+            if (_skip) {
+                break;
+            }
+            audio_data_size = decoder->GetNextData(_audio_buf, AUDIO_WRITE_BUFF_SIZE);
+            if (audio_data_size > 0) {
+                audio.write(_audio_buf, audio_data_size);
+            }
+        }
+        Thread::wait(500);
+        ret = true;
+    }
+    delete decoder;
+    fclose(fp);
+
+    return ret;
+}
+
+bool EasyPlaybackPWM::is_paused(void)
+{
+    return _pause;
+}
+
+void EasyPlaybackPWM::pause()
+{
+    _pause = !_pause;
+}
+
+void EasyPlaybackPWM::pause(bool type)
+{
+    _pause = type;
+}
+
+void EasyPlaybackPWM::skip(void)
+{
+    _skip = true;
+}
+
+bool EasyPlaybackPWM::outputVolume(float VolumeOut)
+{
+    return audio.outputVolume(VolumeOut);
+}
+
+EasyDecoder * EasyPlaybackPWM::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();
+}
+
diff -r 000000000000 -r 41ab76b22961 EasyPlaybackPWM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EasyPlaybackPWM.h	Thu Jul 06 04:42:29 2017 +0000
@@ -0,0 +1,54 @@
+/* mbed EasyPlaybackPWM 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.
+ */
+
+#ifndef __EASY_PLAYBACK_PWM_H__
+#define __EASY_PLAYBACK_PWM_H__
+
+#include <string>
+#include <map>
+#include "EasyDecoder.h"
+#include "PwmOutSpeaker.h"
+
+class EasyPlaybackPWM
+{
+public:
+    EasyPlaybackPWM(PinName pwm_l, PinName pwm_r);
+    ~EasyPlaybackPWM();
+    bool get_tag(const char* filename, char* p_title, char* p_artist, char* p_album, uint16_t tag_size);
+    bool play(const char* filename);
+    bool is_paused(void);
+    void pause(void);
+    void pause(bool type);
+    void skip(void);
+    bool outputVolume(float VolumeOut);
+
+    template<typename T>
+    void add_decoder(const string& extension) {
+        m_lpDecoders[extension] = &T::inst;
+    }
+
+private:
+    #define AUDIO_WRITE_BUFF_SIZE  (4096)
+    PwmOutSpeaker audio;
+    bool _skip;
+    bool _pause;
+    uint8_t *_audio_buf;
+    std::map<std::string, EasyDecoder*(*)()> m_lpDecoders;
+
+    EasyDecoder * create_decoer_class(const char* filename);
+};
+
+#endif
diff -r 000000000000 -r 41ab76b22961 decoder/EasyDec_Wav.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoder/EasyDec_Wav.h	Thu Jul 06 04:42:29 2017 +0000
@@ -0,0 +1,258 @@
+/* mbed EasyDec_Wav 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.
+ */
+
+/**************************************************************************//**
+* @file          EasyDec_Wav.h
+* @brief         wav
+******************************************************************************/
+#ifndef __EASY_DECODER_WAV_H__
+#define __EASY_DECODER_WAV_H__
+
+#include "EasyDecoder.h"
+
+/** A class to communicate a EasyDec_Wav
+ *
+ */
+class EasyDec_Wav : public EasyDecoder {
+public:
+
+    static inline EasyDecoder* inst() { return new EasyDec_Wav; }
+
+    /** analyze header
+     *
+     * @param p_title title tag buffer
+     * @param p_artist artist tag buffer
+     * @param p_album album tag buffer
+     * @param tag_size tag buffer size
+     * @param fp file pointer
+     * @return true = success, false = failure
+     */
+    virtual bool AnalyzeHeder(char* p_title, char* p_artist, char* p_album, uint16_t tag_size, FILE* fp) {
+        bool result = false;
+        size_t read_size;
+        uint8_t wk_read_buff[36];
+        char *data;
+        uint32_t chunk_size;
+        uint32_t sub_chunk_size;
+        uint32_t list_index_max;
+        bool list_ok = false;
+        uint32_t read_index = 0;
+        uint32_t data_index = 0;
+        uint16_t wk_len;
+
+        if (fp == NULL) {
+            return false;
+        }
+        music_data_size  = 0;
+        music_data_index = 0;
+        wav_fp = fp;
+        if (p_title != NULL) {
+            p_title[0] = '\0';
+        }
+        if (p_artist != NULL) {
+            p_artist[0] = '\0';
+        }
+        if (p_album != NULL) {
+            p_album[0] = '\0';
+        }
+
+        read_size = fread(&wk_read_buff[0], sizeof(char), 36, wav_fp);
+        if (read_size < 36) {
+            // do nothing
+        } else if (memcmp(&wk_read_buff[0], "RIFF", 4) != 0) {
+            // do nothing
+        } else if (memcmp(&wk_read_buff[8], "WAVE", 4) != 0) {
+            // do nothing
+        } else if (memcmp(&wk_read_buff[12], "fmt ", 4) != 0) {
+            // do nothing
+        } else {
+            read_index += 36;
+            channel = ((uint32_t)wk_read_buff[22] << 0) + ((uint32_t)wk_read_buff[23] << 8);
+            sampling_rate = ((uint32_t)wk_read_buff[24] << 0)
+                          + ((uint32_t)wk_read_buff[25] << 8)
+                          + ((uint32_t)wk_read_buff[26] << 16)
+                          + ((uint32_t)wk_read_buff[27] << 24);
+            block_size = ((uint32_t)wk_read_buff[34] << 0) + ((uint32_t)wk_read_buff[35] << 8);
+            while (1) {
+                read_size = fread(&wk_read_buff[0], sizeof(char), 8, wav_fp);
+                read_index += 8;
+                if (read_size < 8) {
+                    break;
+                } else {
+                    chunk_size = ((uint32_t)wk_read_buff[4] << 0)
+                               + ((uint32_t)wk_read_buff[5] << 8)
+                               + ((uint32_t)wk_read_buff[6] << 16)
+                               + ((uint32_t)wk_read_buff[7] << 24);
+                    if (memcmp(&wk_read_buff[0], "data", 4) == 0) {
+                        result = true;
+                        music_data_size = chunk_size;
+                        if (list_ok == true) {
+                            break;
+                        } else {
+                            data_index = read_index;
+                            fseek(wav_fp, chunk_size, SEEK_CUR);
+                            read_index += chunk_size;
+                        }
+                    } else if (memcmp(&wk_read_buff[0], "LIST", 4) == 0) {
+                        list_ok = true;
+                        list_index_max = read_index + chunk_size;
+                        read_size = fread(&wk_read_buff[0], sizeof(char), 4, wav_fp);
+                        read_index += 4;
+                        while (read_index < list_index_max) {
+                            read_size = fread(&wk_read_buff[0], sizeof(char), 8, wav_fp);
+                            read_index += 8;
+                            if (read_size < 8) {
+                                break;
+                            } else if (memcmp(&wk_read_buff[0], "INAM", 4) == 0) {
+                                data = p_title;
+                            } else if (memcmp(&wk_read_buff[0], "IART", 4) == 0) {
+                                data = p_artist;
+                            } else if (memcmp(&wk_read_buff[0], "IPRD", 4) == 0) {
+                                data = p_album;
+                            } else {
+                                data = NULL;
+                            }
+                            sub_chunk_size = ((uint32_t)wk_read_buff[4] << 0)
+                                           + ((uint32_t)wk_read_buff[5] << 8)
+                                           + ((uint32_t)wk_read_buff[6] << 16)
+                                           + ((uint32_t)wk_read_buff[7] << 24);
+                            if ((data != NULL) && (tag_size != 0)) {
+                                if (sub_chunk_size > (uint32_t)(tag_size - 1)) {
+                                    wk_len = (tag_size - 1);
+                                } else {
+                                    wk_len = sub_chunk_size;
+                                }
+                                read_size = fread(data, sizeof(char), wk_len, wav_fp);
+                                data[wk_len] = '\0';
+                            }
+                            if ((sub_chunk_size & 0x00000001) != 0) {
+                                sub_chunk_size += 1;
+                            }
+                            read_index += sub_chunk_size;
+                            fseek(wav_fp, read_index, SEEK_SET);
+                        }
+                        if (data_index != 0) {
+                            break;
+                        } else {
+                            fseek(wav_fp, list_index_max, SEEK_SET);
+                        }
+                    } else {
+                        fseek(wav_fp, chunk_size, SEEK_CUR);
+                        read_index += chunk_size;
+                    }
+                }
+            }
+
+            if (data_index != 0) {
+                fseek(wav_fp, data_index, SEEK_SET);
+            }
+        }
+
+        return result;
+    };
+
+    /** get next data
+     *
+     * @param buf data buffer address
+     * @param len data buffer length
+     * @return get data size
+     */
+    virtual size_t GetNextData(void *buf, size_t len) {
+        if (block_size == 24) {
+            // Add padding
+            uint32_t write_index = 0;
+            uint32_t wavfile_index;
+            uint32_t read_len;
+            uint32_t pading_index = 0;
+            uint8_t * p_buf = (uint8_t *)buf;
+            size_t ret;
+
+            if ((music_data_index + len) > music_data_size) {
+                len = music_data_size - music_data_index;
+            }
+            while (write_index < (uint32_t)len) {
+                read_len = (len - write_index) * 3 / 4;
+                if (read_len > sizeof(wk_wavfile_buff)) {
+                    read_len = sizeof(wk_wavfile_buff);
+                }
+                music_data_index += read_len;
+                ret = fread(wk_wavfile_buff, sizeof(char), read_len, wav_fp);
+                if (ret < read_len) {
+                    break;
+                }
+                wavfile_index = 0;
+                while ((write_index < len) && (wavfile_index < read_len)) {
+                    if (pading_index == 0) {
+                        p_buf[write_index] = 0;
+                    } else {
+                        p_buf[write_index] = wk_wavfile_buff[wavfile_index];
+                        wavfile_index++;
+                    }
+                    if (pading_index < 3) {
+                        pading_index++;
+                    } else {
+                        pading_index = 0;
+                    }
+                    write_index++;
+                }
+            }
+
+            return write_index;
+        } else {
+            if ((music_data_index + len) > music_data_size) {
+                len = music_data_size - music_data_index;
+            }
+            music_data_index += len;
+
+            return fread(buf, sizeof(char), len, wav_fp);
+        }
+    };
+
+    /** get channel
+     *
+     * @return channel
+     */
+    virtual uint16_t GetChannel() {
+        return channel;
+    };
+
+    /** get block size
+     *
+     * @return block size
+     */
+    virtual uint16_t GetBlockSize() {
+        return block_size;
+    };
+
+    /** get sampling rate
+     *
+     * @return sampling rate
+     */
+    virtual uint32_t GetSamplingRate() {
+        return sampling_rate;
+    };
+
+private:
+    FILE * wav_fp;
+    uint32_t music_data_size;
+    uint32_t music_data_index;
+    uint16_t channel;
+    uint16_t block_size;
+    uint32_t sampling_rate;
+    uint8_t wk_wavfile_buff[3072];
+};
+
+#endif
diff -r 000000000000 -r 41ab76b22961 decoder/EasyDec_WavCnv2ch.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoder/EasyDec_WavCnv2ch.h	Thu Jul 06 04:42:29 2017 +0000
@@ -0,0 +1,299 @@
+/* mbed EasyDec_WavCnv2ch 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.
+ */
+
+/**************************************************************************//**
+* @file          EasyDec_WavCnv2ch.h
+* @brief         wav
+******************************************************************************/
+#ifndef __EASY_DEC_WAV_CNV_2CH_H__
+#define __EASY_DEC_WAV_CNV_2CH_H__
+
+#include "EasyDecoder.h"
+
+/** A class to communicate a EasyDec_WavCnv2ch
+ *
+ */
+class EasyDec_WavCnv2ch : public EasyDecoder {
+public:
+
+    static inline EasyDecoder* inst() { return new EasyDec_WavCnv2ch; }
+
+    /** analyze header
+     *
+     * @param p_title title tag buffer
+     * @param p_artist artist tag buffer
+     * @param p_album album tag buffer
+     * @param tag_size tag buffer size
+     * @param fp file pointer
+     * @return true = success, false = failure
+     */
+    virtual bool AnalyzeHeder(char* p_title, char* p_artist, char* p_album, uint16_t tag_size, FILE* fp) {
+        bool result = false;
+        size_t read_size;
+        uint8_t wk_read_buff[36];
+        char *data;
+        uint32_t chunk_size;
+        uint32_t sub_chunk_size;
+        uint32_t list_index_max;
+        bool list_ok = false;
+        uint32_t read_index = 0;
+        uint32_t data_index = 0;
+        uint16_t wk_len;
+
+        if (fp == NULL) {
+            return false;
+        }
+        music_data_size  = 0;
+        music_data_index = 0;
+        wav_fp = fp;
+        if (p_title != NULL) {
+            p_title[0] = '\0';
+        }
+        if (p_artist != NULL) {
+            p_artist[0] = '\0';
+        }
+        if (p_album != NULL) {
+            p_album[0] = '\0';
+        }
+
+        read_size = fread(&wk_read_buff[0], sizeof(char), 36, wav_fp);
+        if (read_size < 36) {
+            // do nothing
+        } else if (memcmp(&wk_read_buff[0], "RIFF", 4) != 0) {
+            // do nothing
+        } else if (memcmp(&wk_read_buff[8], "WAVE", 4) != 0) {
+            // do nothing
+        } else if (memcmp(&wk_read_buff[12], "fmt ", 4) != 0) {
+            // do nothing
+        } else {
+            read_index += 36;
+            channel = ((uint32_t)wk_read_buff[22] << 0) + ((uint32_t)wk_read_buff[23] << 8);
+            sampling_rate = ((uint32_t)wk_read_buff[24] << 0)
+                          + ((uint32_t)wk_read_buff[25] << 8)
+                          + ((uint32_t)wk_read_buff[26] << 16)
+                          + ((uint32_t)wk_read_buff[27] << 24);
+            block_size = ((uint32_t)wk_read_buff[34] << 0) + ((uint32_t)wk_read_buff[35] << 8);
+            while (1) {
+                read_size = fread(&wk_read_buff[0], sizeof(char), 8, wav_fp);
+                read_index += 8;
+                if (read_size < 8) {
+                    break;
+                } else {
+                    chunk_size = ((uint32_t)wk_read_buff[4] << 0)
+                               + ((uint32_t)wk_read_buff[5] << 8)
+                               + ((uint32_t)wk_read_buff[6] << 16)
+                               + ((uint32_t)wk_read_buff[7] << 24);
+                    if (memcmp(&wk_read_buff[0], "data", 4) == 0) {
+                        result = true;
+                        music_data_size = chunk_size;
+                        if (list_ok == true) {
+                            break;
+                        } else {
+                            data_index = read_index;
+                            fseek(wav_fp, chunk_size, SEEK_CUR);
+                            read_index += chunk_size;
+                        }
+                    } else if (memcmp(&wk_read_buff[0], "LIST", 4) == 0) {
+                        list_ok = true;
+                        list_index_max = read_index + chunk_size;
+                        read_size = fread(&wk_read_buff[0], sizeof(char), 4, wav_fp);
+                        read_index += 4;
+                        while (read_index < list_index_max) {
+                            read_size = fread(&wk_read_buff[0], sizeof(char), 8, wav_fp);
+                            read_index += 8;
+                            if (read_size < 8) {
+                                break;
+                            } else if (memcmp(&wk_read_buff[0], "INAM", 4) == 0) {
+                                data = p_title;
+                            } else if (memcmp(&wk_read_buff[0], "IART", 4) == 0) {
+                                data = p_artist;
+                            } else if (memcmp(&wk_read_buff[0], "IPRD", 4) == 0) {
+                                data = p_album;
+                            } else {
+                                data = NULL;
+                            }
+                            sub_chunk_size = ((uint32_t)wk_read_buff[4] << 0)
+                                           + ((uint32_t)wk_read_buff[5] << 8)
+                                           + ((uint32_t)wk_read_buff[6] << 16)
+                                           + ((uint32_t)wk_read_buff[7] << 24);
+                            if ((data != NULL) && (tag_size != 0)) {
+                                if (sub_chunk_size > (uint32_t)(tag_size - 1)) {
+                                    wk_len = (tag_size - 1);
+                                } else {
+                                    wk_len = sub_chunk_size;
+                                }
+                                read_size = fread(data, sizeof(char), wk_len, wav_fp);
+                                data[wk_len] = '\0';
+                            }
+                            if ((sub_chunk_size & 0x00000001) != 0) {
+                                sub_chunk_size += 1;
+                            }
+                            read_index += sub_chunk_size;
+                            fseek(wav_fp, read_index, SEEK_SET);
+                        }
+                        if (data_index != 0) {
+                            break;
+                        } else {
+                            fseek(wav_fp, list_index_max, SEEK_SET);
+                        }
+                    } else {
+                        fseek(wav_fp, chunk_size, SEEK_CUR);
+                        read_index += chunk_size;
+                    }
+                }
+            }
+
+            if (data_index != 0) {
+                fseek(wav_fp, data_index, SEEK_SET);
+            }
+        }
+
+        return result;
+    };
+
+    /** get next data
+     *
+     * @param buf data buffer address
+     * @param len data buffer length
+     * @return get data size
+     */
+    virtual size_t GetNextData(void *buf, size_t len) {
+        size_t ret_size;
+        size_t read_max = len;
+
+        if ((block_size < 8) || ((block_size & 0x07) != 0)) {
+            return -1;
+        }
+
+        if ((channel == 1) && (len != 0)) {
+            read_max /= 2;
+        }
+
+        if (block_size == 24) {
+            // Add padding
+            uint32_t write_index = 0;
+            uint32_t wavfile_index;
+            uint32_t read_len;
+            uint32_t pading_index = 0;
+            uint8_t * p_buf = (uint8_t *)buf;
+            size_t ret;
+
+            if ((music_data_index + read_max) > music_data_size) {
+                read_max = music_data_size - music_data_index;
+            }
+            while (write_index < (uint32_t)read_max) {
+                read_len = (read_max - write_index) * 3 / 4;
+                if (read_len > sizeof(wk_wavfile_buff)) {
+                    read_len = sizeof(wk_wavfile_buff);
+                }
+                music_data_index += read_len;
+                ret = fread(wk_wavfile_buff, sizeof(char), read_len, wav_fp);
+                if (ret < read_len) {
+                    break;
+                }
+                wavfile_index = 0;
+                while ((write_index < read_max) && (wavfile_index < read_len)) {
+                    if (pading_index == 0) {
+                        p_buf[write_index] = 0;
+                    } else {
+                        p_buf[write_index] = wk_wavfile_buff[wavfile_index];
+                        wavfile_index++;
+                    }
+                    if (pading_index < 3) {
+                        pading_index++;
+                    } else {
+                        pading_index = 0;
+                    }
+                    write_index++;
+                }
+            }
+            ret_size = write_index;
+        } else {
+            if ((music_data_index + read_max) > music_data_size) {
+                read_max = music_data_size - music_data_index;
+            }
+            music_data_index += read_max;
+
+            ret_size = fread(buf, sizeof(char), read_max, wav_fp);
+        }
+
+        if ((channel == 1) && (ret_size > 0)) {
+            int block_byte;
+            int idx_w = len - 1;
+            int idx_r = ret_size - 1;
+            int idx_r_last;
+            int j;
+
+            if (block_size == 24) {
+                block_byte = 4;
+            } else {
+                block_byte = block_size / 8;
+            }
+            while (idx_w >= 0) {
+                idx_r_last = idx_r;
+                for (j = 0; j < block_byte; j++) {
+                    ((uint8_t*)buf)[idx_w--] = ((uint8_t*)buf)[idx_r--];
+                }
+                idx_r = idx_r_last;
+                for (j = 0; j < block_byte; j++) {
+                    ((uint8_t*)buf)[idx_w--] = ((uint8_t*)buf)[idx_r--];
+                }
+            }
+            ret_size *= 2;
+        }
+
+        return ret_size;
+    };
+
+    /** get channel
+     *
+     * @return channel
+     */
+    virtual uint16_t GetChannel() {
+        if (channel == 1) {
+            return 2;
+        } else {
+            return channel;
+        }
+    };
+
+    /** get block size
+     *
+     * @return block size
+     */
+    virtual uint16_t GetBlockSize() {
+        return block_size;
+    };
+
+    /** get sampling rate
+     *
+     * @return sampling rate
+     */
+    virtual uint32_t GetSamplingRate() {
+        return sampling_rate;
+    };
+
+private:
+    FILE * wav_fp;
+    uint32_t music_data_size;
+    uint32_t music_data_index;
+    uint16_t channel;
+    uint16_t block_size;
+    uint32_t sampling_rate;
+    uint8_t wk_wavfile_buff[3072];
+};
+
+#endif
diff -r 000000000000 -r 41ab76b22961 decoder/EasyDecoder.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/decoder/EasyDecoder.h	Thu Jul 06 04:42:29 2017 +0000
@@ -0,0 +1,66 @@
+/* mbed EasyDecoder 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.
+ */
+
+#ifndef __EASY_DECODER_H__
+#define __EASY_DECODER_H__
+
+#include "mbed.h"
+
+class EasyDecoder {
+public:
+
+    virtual ~EasyDecoder(){}
+
+    /** analyze header
+     *
+     * @param p_title title tag buffer
+     * @param p_artist artist tag buffer
+     * @param p_album album tag buffer
+     * @param tag_size tag buffer size
+     * @param fp file pointer
+     * @return true = success, false = failure
+     */
+    virtual bool AnalyzeHeder(char* p_title, char* p_artist, char* p_album, uint16_t tag_size, FILE* fp) = 0;
+
+    /** get next data
+     *
+     * @param buf data buffer address
+     * @param len data buffer length
+     * @return get data size
+     */
+    virtual size_t GetNextData(void *buf, size_t len) = 0;
+
+    /** get channel
+     *
+     * @return channel
+     */
+    virtual uint16_t GetChannel() = 0;
+
+    /** get block size
+     *
+     * @return block size
+     */
+    virtual uint16_t GetBlockSize() = 0;
+
+    /** get sampling rate
+     *
+     * @return sampling rate
+     */
+    virtual uint32_t GetSamplingRate() = 0;
+
+};
+
+#endif