Repository: r9y9/pysinsy (language: python)

Issue:
Remove dep. with shared libraries
We can do something similar with https://github.com/r9y9/pyopenjtalk/issues/7 to avoid installation burden. 
Remove dep. with shared libraries
We can do something similar with https://github.com/r9y9/pyopenjtalk/issues/7 to avoid installation burden. 


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 75a530a..43744e7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,25 +12,16 @@ on:
 jobs:
   build:
 
-    runs-on: ubuntu-latest
+    runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        python-version: [3.5, 3.6, 3.7, 3.8]
+        os: [ubuntu-latest, windows-latest]
+        python-version: [3.7, 3.8, 3.9]
 
     steps:
     - uses: actions/checkout@v2
-    - name: install hts_engine_API
-      run: |
-        git clone https://github.com/r9y9/hts_engine_API
-        cd hts_engine_API/src && mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON .. && sudo make install
-        cd ../../ && rm -rf hts_engine_API
-    - name: install sinsy
-      run: |
-        git clone https://github.com/r9y9/sinsy
-        cd sinsy/src/ && mkdir -p build && cd build
-        cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON .. && make -j && sudo make install
-        cd ../../../ && rm -rf sinsy
-
+      with:
+        submodules: recursive
     - name: Set up Python ${{ matrix.python-version }}
       uses: actions/setup-python@v1
       with:
@@ -38,14 +29,11 @@ jobs:
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install -r requirements.txt
-        pip install -e .
-    - name: Lint with flake8
+        pip install -e ".[lint]"
+    - name: Lint with pysen
       run: |
-        pip install flake8
-        flake8
+        pysen run lint
     - name: Test with pytest
       run: |
-        export LD_LIBRARY_PATH=/usr/local/lib
         pip install pytest
-        pytest
+        pytest
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..2c3175a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/sinsy"]
+	path = lib/sinsy
+	url = https://github.com/r9y9/sinsy.git
diff --git a/lib/sinsy b/lib/sinsy
new file mode 160000
index 0000000..c69a504
--- /dev/null
+++ b/lib/sinsy
@@ -0,0 +1,1 @@
+Subproject commit c69a5042a682c287a3eaaf44bb5b30a0b41df7bf
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..8d1266b
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,21 @@
+[build-system]
+requires = [
+    "wheel",
+    "setuptools",
+    "cython>=0.21.0",
+    "numpy<v1.20.0",
+]
+
+[tool.pysen]
+version = "0.9"
+
+[tool.pysen.lint]
+enable_black = true
+enable_flake8 = true
+enable_isort = true
+enable_mypy = false # TODO: enable mypy in the future
+mypy_preset = "strict"
+line_length = 88
+py_version = "py37"
+[[tool.pysen.lint.mypy_targets]]
+  paths = ["."]
\ No newline at end of file
diff --git a/pysinsy/__init__.py b/pysinsy/__init__.py
index 2c3ce2d..2aefdb7 100644
--- a/pysinsy/__init__.py
+++ b/pysinsy/__init__.py
@@ -1,11 +1,61 @@
-# coding: utf-8
-
-from .version import __version__
+import pkg_resources
 
 from .sinsy import Sinsy
+from .version import __version__  # noqa
+
+DEFAULT_DIC_DIR = pkg_resources.resource_filename(__name__, "_dic")
 
+DEFAULT_HTS_VOICE = pkg_resources.resource_filename(
+    __name__, "htsvoice/nitech_jp_song070_f001.htsvoice"
+)
+
+# Global instance of sinsy
 _global_sinsy = None
 
 
+def get_default_dic_dir():
+    """Returns default dictionary directory
+
+    Returns:
+        str: dictionary path
+    """
+    return DEFAULT_DIC_DIR
+
+
+def get_default_htsvoice():
+    """Returns default hts voice
+
+    Returns:
+        str: hts voice path
+    """
+    return DEFAULT_HTS_VOICE
+
+
 def _lazy_init():
-    pass
+    global _global_sinsy
+    _global_sinsy = Sinsy()
+    _global_sinsy.setLanguages("j", get_default_dic_dir())
+    _global_sinsy.loadVoices(get_default_htsvoice())
+
+
+def synthesize(musicxml_path: str):
+    """Synthesize waveform given muxic XML file
+
+    Args:
+        str: music XML path
+
+    Returns:
+        tuple: tuple of wav array of type float64 and sampling frequency
+
+    Raises:
+        RuntimeError: if fail to synthesize
+    """
+    global _global_sinsy
+    if _global_sinsy is None:
+        _lazy_init()
+
+    _global_sinsy.loadScoreFromMusicXML(musicxml_path)
+    wav, sr = _global_sinsy.synthesize()
+    _global_sinsy.clearScore()
+
+    return wav, sr
diff --git a/pysinsy/_dic/COPYING b/pysinsy/_dic/COPYING
new file mode 100644
index 0000000..854f722
--- /dev/null
+++ b/pysinsy/_dic/COPYING
@@ -0,0 +1,40 @@
+/* ----------------------------------------------------------------- */
+/*           The HMM-Based Singing Voice Synthesis System "Sinsy"    */
+/*           developed by Sinsy Working Group                        */
+/*           http://sinsy.sourceforge.net/                           */
+/* ----------------------------------------------------------------- */
+/*                                                                   */
+/*  Copyright (c) 2009-2015  Nagoya Institute of Technology          */
+/*                           Department of Computer Science          */
+/*                                                                   */
+/* All rights reserved.                                              */
+/*                                                                   */
+/* Redistribution and use in source and binary forms, with or        */
+/* without modification, are permitted provided that the following   */
+/* conditions are met:                                               */
+/*                                                                   */
+/* - Redistributions of source code must retain the above copyright  */
+/*   notice, this list of conditions and the following disclaimer.   */
+/* - Redistributions in binary form must reproduce the above         */
+/*   copyright notice, this list of conditions and the following     */
+/*   disclaimer in the documentation and/or other materials provided */
+/*   with the distribution.                                          */
+/* - Neither the name of the Sinsy working group nor the names of    */
+/*   its contributors may be used to endorse or promote products     */
+/*   derived from this software without specific prior written       */
+/*   permission.                                                     */
+/*                                                                   */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND            */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,       */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF          */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */
+/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          */
+/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED   */
+/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     */
+/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
+/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,   */
+/* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY    */
+/* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
+/* POSSIBILITY OF SUCH DAMAGE.                                       */
+/* ----------------------------------------------------------------- */
diff --git a/pysinsy/_dic/japanese.euc_jp.conf b/pysinsy/_dic/japanese.euc_jp.conf
new file mode 100644
index 0000000..1ba8ec1
--- /dev/null
+++ b/pysinsy/_dic/japanese.euc_jp.conf
@@ -0,0 +1,5 @@
+MACRON="��"
+PHONEME_CL="cl"
+VOWEL_REDUCTION="��"
+VOWELS="a,i,u,e,o,N"
+MULTIBYTE_CHAR_RANGE="2,0xA1,0xFE;3,0x8F,0x8F"
diff --git a/pysinsy/_dic/japanese.euc_jp.table b/pysinsy/_dic/japanese.euc_jp.table
new file mode 100644
index 0000000..2c63b6f
--- /dev/null
+++ b/pysinsy/_dic/japanese.euc_jp.table
@@ -0,0 +1,345 @@
+���� k w a
+���� k w i
+���� k w u
+���� k w e
+���� k w o
+���� k w a
+���� g w a
+���� g w i
+���� g w u
+���� g w e
+���� g w o
+���� g w a
+���� k w a
+���� k w i
+���� k w u
+���� k w e
+���� k w o
+���� k w a
+���� g w a
+���� g w i
+���� g w u
+���� g w e
+���� g w o
+���� g w a
+�� N
+�� o
+�� e
+�� i
+�� w a
+�� w a
+�� r o
+�� r e
+�� r u
+��� ry o
+��� ry u
+��� ry a
+�ꤧ ry e
+�� r i
+�� r a
+�� y o
+�� y o
+�� y u
+�� y u
+�� y a
+�� y a
+�� m o
+�� m e
+�� m u
+�ߤ� my o
+�ߤ� my u
+�ߤ� my a
+�ߤ� my e
+�� m i
+�� m a
+�� p o
+�� b o
+�� h o
+�� p e
+�� b e
+�� h e
+�� p u
+�� b u
+�դ� f o
+�դ� f e
+�դ� f i
+�դ� f a
+�� f u
+�Ԥ� py o
+�Ԥ� py u
+�Ԥ� py a
+�Ԥ� py e
+�� p i
+�Ӥ� by o
+�Ӥ� by u
+�Ӥ� by a
+�Ӥ� by e
+�� b i
+�Ҥ� hy o
+�Ҥ� hy u
+�Ҥ� hy a
+�Ҥ� hy e
+�� h i
+�� p a
+�� b a
+�� h a
+�� n o
+�� n e
+�� n u
+�ˤ� ny o
+�ˤ� ny u
+�ˤ� ny a
+�ˤ� ny e
+�� n i
+�� n a
+�ɤ� d u
+�� d o
+�Ȥ� t u
+�� t o
+�Ǥ� dy o
+�Ǥ� dy u
+�Ǥ� dy a
+�Ǥ� dy e
+�Ǥ� d i
+�� d e
+�Ƥ� ty o
+�Ƥ� ty u
+�Ƥ� ty a
+�Ƥ� t i
+�� t e
+�� z u
+�Ĥ� ts o
+�Ĥ� ts e
+�Ĥ� ts i
+�Ĥ� ts a
+�� ts u
+�� cl
+�� j i
+���� ch o
+���� ch u
+���� ch a
+���� ch e
+�� ch i
+�� d a
+�� t a
+�� z o
+�� s o
+�� z e
+�� s e
+���� z i
+�� z u
+���� s i
+�� s u
+���� j o
+���� j u
+���� j a
+���� j e
+�� j i
+���� sh o
+���� sh u
+���� sh a
+���� sh e
+���� s i
+�� sh i
+�� z a
+�� s a
+�� g o
+�� k o
+�� g e
+�� k e
+�� g u
+�� k u
+���� gy o
+���� gy u
+���� gy a
+���� gy e
+�� g i
+���� ky o
+���� ky u
+���� ky a
+���� ky e
+�� k i
+�� g a
+�� k a
+�� o
+�� o
+�� e
+�� e
+���� w o
+���� w e
+���� w i
+�� u
+�� u
+���� y e
+�� i
+�� i
+�� a
+�� a
+���� by o
+���� by u
+���� by a
+���� v o
+���� v e
+���� v i
+���� v a
+���� by o
+���� by u
+���� by a
+���� v o
+���� v e
+���� v i
+���� v a
+�� v u
+�� N
+�� o
+�� e
+�� i
+�� w a
+�� w a
+�� r o
+�� r e
+�� r u
+��� ry o
+��� ry u
+��� ry a
+�ꥧ ry e
+�� r i
+�� r a
+�� y o
+�� y o
+�� y u
+�� y u
+�� y a
+�� y a
+�� m o
+�� m e
+�� m u
+�ߥ� my o
+�ߥ� my u
+�ߥ� my a
+�ߥ� my e
+�� m i
+�� m a
+�� p o
+�� b o
+�� h o
+�� p e
+�� b e
+�� h e
+�� p u
+�� b u
+�ե� f o
+�ե� f e
+�ե� f i
+�ե� f a
+�� f u
+�ԥ� py o
+�ԥ� py u
+�ԥ� py a
+�ԥ� py e
+�� p i
+�ӥ� by o
+�ӥ� by u
+�ӥ� by a
+�ӥ� by e
+�� b i
+�ҥ� hy o
+�ҥ� hy u
+�ҥ� hy a
+�ҥ� hy e
+�� h i
+�� p a
+�� b a
+�� h a
+�� n o
+�� n e
+�� n u
+�˥� ny o
+�˥� ny u
+�˥� ny a
+�˥� ny e
+�� n i
+�� n a
+�ɥ� d u
+�� d o
+�ȥ� t u
+�� t o
+�ǥ� dy o
+�ǥ� dy u
+�ǥ� dy a
+�ǥ� dy e
+�ǥ� d i
+�� d e
+�ƥ� ty o
+�ƥ� ty u
+�ƥ� ty a
+�ƥ� t i
+�� t e
+�� z u
+�ĥ� ts o
+�ĥ� ts e
+�ĥ� ts i
+�ĥ� ts a
+�� ts u
+�� cl
+�� j i
+���� ch o
+���� ch u
+���� ch a
+���� ch e
+�� ch i
+�� d a
+�� t a
+�� z o
+�� s o
+�� z e
+�� s e
+���� z i
+�� z u
+���� s i
+�� s u
+���� j o
+���� j u
+���� j a
+���� j e
+�� j i
+���� sh o
+���� sh u
+���� sh a
+���� sh e
+���� s i
+�� sh i
+�� z a
+�� s a
+�� g o
+�� k o
+�� g e
+�� k e
+�� g u
+�� k u
+���� gy o
+���� gy u
+���� gy a
+���� gy e
+�� g i
+���� ky o
+���� ky u
+���� ky a
+���� ky e
+�� k i
+�� g a
+�� k a
+�� o
+�� o
+�� e
+�� e
+���� w o
+���� w e
+���� w i
+�� u
+�� u
+���� y e
+�� i
+�� i
+�� a
+�� a
diff --git a/pysinsy/_dic/japanese.macron b/pysinsy/_dic/japanese.macron
new file mode 100644
index 0000000..e69de29
diff --git a/pysinsy/_dic/japanese.shift_jis.conf b/pysinsy/_dic/japanese.shift_jis.conf
new file mode 100644
index 0000000..f9101fa
--- /dev/null
+++ b/pysinsy/_dic/japanese.shift_jis.conf
@@ -0,0 +1,5 @@
+MACRON="�["
+PHONEME_CL="cl"
+VOWEL_REDUCTION="�f"
+VOWELS="a,i,u,e,o,N"
+MULTIBYTE_CHAR_RANGE="2,0x81,0xFC"
diff --git a/pysinsy/_dic/japanese.shift_jis.table b/pysinsy/_dic/japanese.shift_jis.table
new file mode 100644
index 0000000..d22e955
--- /dev/null
+++ b/pysinsy/_dic/japanese.shift_jis.table
@@ -0,0 +1,345 @@
+�N�@ k w a
+�N�B k w i
+�N�D k w u
+�N�F k w e
+�N�H k w o
+�N�� k w a
+�O�@ g w a
+�O�B g w i
+�O�D g w u
+�O�F g w e
+�O�H g w o
+�O�� g w a
+���� k w a
+���� k w i
+���� k w u
+���� k w e
+���� k w o
+���� k w a
+���� g w a
+���� g w i
+���� g w u
+���� g w e
+���� g w o
+���� g w a
+�� N
+�� o
+�� e
+�� i
+�� w a
+�� w a
+�� r o
+�� r e
+�� r u
+��� ry o
+��� ry u
+��� ry a
+�肥 ry e
+�� r i
+�� r a
+�� y o
+�� y o
+�� y u
+�� y u
+�� y a
+�� y a
+�� m o
+�� m e
+�� m u
+�݂� my o
+�݂� my u
+�݂� my a
+�݂� my e
+�� m i
+�� m a
+�� p o
+�� b o
+�� h o
+�� p e
+�� b e
+�� h e
+�� p u
+�� b u
+�ӂ� f o
+�ӂ� f e
+�ӂ� f i
+�ӂ� f a
+�� f u
+�҂� py o
+�҂� py u
+�҂� py a
+�҂� py e
+�� p i
+�т� by o
+�т� by u
+�т� by a
+�т� by e
+�� b i
+�Ђ� hy o
+�Ђ� hy u
+�Ђ� hy a
+�Ђ� hy e
+�� h i
+�� p a
+�� b a
+�� h a
+�� n o
+�� n e
+�� n u
+�ɂ� ny o
+�ɂ� ny u
+�ɂ� ny a
+�ɂ� ny e
+�� n i
+�� n a
+�ǂ� d u
+�� d o
+�Ƃ� t u
+�� t o
+�ł� dy o
+�ł� dy u
+�ł� dy a
+�ł� dy e
+�ł� d i
+�� d e
+�Ă� ty o
+�Ă� ty u
+�Ă� ty a
+�Ă� t i
+�� t e
+�� z u
+�� ts o
+�� ts e
+�� ts i
+�� ts a
+�� ts u
+�� cl
+�� j i
+���� ch o
+���� ch u
+���� ch a
+���� ch e
+�� ch i
+�� d a
+�� t a
+�� z o
+�� s o
+�� z e
+�� s e
+���� z i
+�� z u
+���� s i
+�� s u
+���� j o
+���� j u
+���� j a
+���� j e
+�� j i
+���� sh o
+���� sh u
+���� sh a
+���� sh e
+���� s i
+�� sh i
+�� z a
+�� s a
+�� g o
+�� k o
+�� g e
+�� k e
+�� g u
+�� k u
+���� gy o
+���� gy u
+���� gy a
+���� gy e
+�� g i
+���� ky o
+���� ky u
+���� ky a
+���� ky e
+�� k i
+�� g a
+�� k a
+�� o
+�� o
+�� e
+�� e
+���� w o
+���� w e
+���� w i
+�� u
+�� u
+���� y e
+�� i
+�� i
+�� a
+�� a
+���� by o
+���� by u
+���� by a
+���� v o
+���� v e
+���� v i
+���� v a
+���� by o
+���� by u
+���� by a
+���H v o
+���F v e
+���B v i
+���@ v a
+�� v u
+�� N
+�� o
+�� e
+�� i
+�� w a
+�� w a
+�� r o
+�� r e
+�� r u
+���� ry o
+���� ry u
+���� ry a
+���F ry e
+�� r i
+�� r a
+�� y o
+�� y o
+�� y u
+�� y u
+�� y a
+�� y a
+�� m o
+�� m e
+�� m u
+�~�� my o
+�~�� my u
+�~�� my a
+�~�F my e
+�~ m i
+�} m a
+�| p o
+�{ b o
+�z h o
+�y p e
+�x b e
+�w h e
+�v p u
+�u b u
+�t�H f o
+�t�F f e
+�t�B f i
+�t�@ f a
+�t f u
+�s�� py o
+�s�� py u
+�s�� py a
+�s�F py e
+�s p i
+�r�� by o
+�r�� by u
+�r�� by a
+�r�F by e
+�r b i
+�q�� hy o
+�q�� hy u
+�q�� hy a
+�q�F hy e
+�q h i
+�p p a
+�o b a
+�n h a
+�m n o
+�l n e
+�k n u
+�j�� ny o
+�j�� ny u
+�j�� ny a
+�j�F ny e
+�j n i
+�i n a
+�h�D d u
+�h d o
+�g�D t u
+�g t o
+�f�� dy o
+�f�� dy u
+�f�� dy a
+�f�F dy e
+�f�B d i
+�f d e
+�e�� ty o
+�e�� ty u
+�e�� ty a
+�e�B t i
+�e t e
+�d z u
+�c�H ts o
+�c�F ts e
+�c�B ts i
+�c�@ ts a
+�c ts u
+�b cl
+�a j i
+�`�� ch o
+�`�� ch u
+�`�� ch a
+�`�F ch e
+�` ch i
+�_ d a
+�^ t a
+�] z o
+�\ s o
+�[ z e
+�Z s e
+�Y�B z i
+�Y z u
+�X�B s i
+�X s u
+�W�� j o
+�W�� j u
+�W�� j a
+�W�F j e
+�W j i
+�V�� sh o
+�V�� sh u
+�V�� sh a
+�V�F sh e
+�V�B s i
+�V sh i
+�U z a
+�T s a
+�S g o
+�R k o
+�Q g e
+�P k e
+�O g u
+�N k u
+�M�� gy o
+�M�� gy u
+�M�� gy a
+�M�F gy e
+�M g i
+�L�� ky o
+�L�� ky u
+�L�� ky a
+�L�F ky e
+�L k i
+�K g a
+�J k a
+�I o
+�H o
+�G e
+�F e
+�E�H w o
+�E�F w e
+�E�B w i
+�E u
+�D u
+�C�F y e
+�C i
+�B i
+�A a
+�@ a
diff --git a/pysinsy/_dic/japanese.utf_8.conf b/pysinsy/_dic/japanese.utf_8.conf
new file mode 100644
index 0000000..e40b3bc
--- /dev/null
+++ b/pysinsy/_dic/japanese.utf_8.conf
@@ -0,0 +1,4 @@
+MACRON="ー"
+PHONEME_CL="cl"
+VOWEL_REDUCTION="’"
+VOWELS="a,i,u,e,o,N"
diff --git a/pysinsy/_dic/japanese.utf_8.table b/pysinsy/_dic/japanese.utf_8.table
new file mode 100644
index 0000000..5df16cd
--- /dev/null
+++ b/pysinsy/_dic/japanese.utf_8.table
@@ -0,0 +1,353 @@
+クァ k w a
+クィ k w i
+クゥ k w u
+クェ k w e
+クォ k w o
+クヮ k w a
+グァ g w a
+グィ g w i
+グゥ g w u
+グェ g w e
+グォ g w o
+グヮ g w a
+くぁ k w a
+くぃ k w i
+くぅ k w u
+くぇ k w e
+くぉ k w o
+くゎ k w a
+ぐぁ g w a
+ぐぃ g w i
+ぐぅ g w u
+ぐぇ g w e
+ぐぉ g w o
+ぐゎ g w a
+ゔょ by o
+ゔゅ by u
+ゔゃ by a
+ゔぉ v o
+ゔぇ v e
+ゔぃ v i
+ゔぁ v a
+ゔ v u
+ん N
+を o
+ゑ e
+ゐ i
+わ w a
+ゎ w a
+ろ r o
+れ r e
+る r u
+りょ ry o
+りゅ ry u
+りゃ ry a
+りぇ ry e
+り r i
+ら r a
+よ y o
+ょ y o
+ゆ y u
+ゅ y u
+や y a
+ゃ y a
+も m o
+め m e
+む m u
+みょ my o
+みゅ my u
+みゃ my a
+みぇ my e
+み m i
+ま m a
+ぽ p o
+ぼ b o
+ほ h o
+ぺ p e
+べ b e
+へ h e
+ぷ p u
+ぶ b u
+ふぉ f o
+ふぇ f e
+ふぃ f i
+ふぁ f a
+ふ f u
+ぴょ py o
+ぴゅ py u
+ぴゃ py a
+ぴぇ py e
+ぴ p i
+びょ by o
+びゅ by u
+びゃ by a
+びぇ by e
+び b i
+ひょ hy o
+ひゅ hy u
+ひゃ hy a
+ひぇ hy e
+ひ h i
+ぱ p a
+ば b a
+は h a
+の n o
+ね n e
+ぬ n u
+にょ ny o
+にゅ ny u
+にゃ ny a
+にぇ ny e
+に n i
+な n a
+どぅ d u
+ど d o
+とぅ t u
+と t o
+でょ dy o
+でゅ dy u
+でゃ dy a
+でぇ dy e
+でぃ d i
+で d e
+てょ ty o
+てゅ ty u
+てゃ ty a
+てぃ t i
+て t e
+づ z u
+つぉ ts o
+つぇ ts e
+つぃ ts i
+つぁ ts a
+つ ts u
+っ cl
+ぢ j i
+ちょ ch o
+ちゅ ch u
+ちゃ ch a
+ちぇ ch e
+ち ch i
+だ d a
+た t a
+ぞ z o
+そ s o
+ぜ z e
+せ s e
+ずぃ z i
+ず z u
+すぃ s i
+す s u
+じょ j o
+じゅ j u
+じゃ j a
+じぇ j e
+じ j i
+しょ sh o
+しゅ sh u
+しゃ sh a
+しぇ sh e
+しぃ s i
+し sh i
+ざ z a
+さ s a
+ご g o
+こ k o
+げ g e
+け k e
+ぐ g u
+く k u
+ぎょ gy o
+ぎゅ gy u
+ぎゃ gy a
+ぎぇ gy e
+ぎ g i
+きょ ky o
+きゅ ky u
+きゃ ky a
+きぇ ky e
+き k i
+が g a
+か k a
+お o
+ぉ o
+え e
+ぇ e
+うぉ w o
+うぇ w e
+うぃ w i
+う u
+ぅ u
+いぇ y e
+い i
+ぃ i
+あ a
+ぁ a
+ヴょ by o
+ヴゅ by u
+ヴゃ by a
+ヴぉ v o
+ヴぇ v e
+ヴぃ v i
+ヴぁ v a
+ヴョ by o
+ヴュ by u
+ヴャ by a
+ヴォ v o
+ヴェ v e
+ヴィ v i
+ヴァ v a
+ヴ v u
+ン N
+ヲ o
+ヱ e
+ヰ i
+ワ w a
+ヮ w a
+ロ r o
+レ r e
+ル r u
+リョ ry o
+リュ ry u
+リャ ry a
+リェ ry e
+リ r i
+ラ r a
+ヨ y o
+ョ y o
+ユ y u
+ュ y u
+ヤ y a
+ャ y a
+モ m o
+メ m e
+ム m u
+ミョ my o
+ミュ my u
+ミャ my a
+ミェ my e
+ミ m i
+マ m a
+ポ p o
+ボ b o
+ホ h o
+ペ p e
+ベ b e
+ヘ h e
+プ p u
+ブ b u
+フォ f o
+フェ f e
+フィ f i
+ファ f a
+フ f u
+ピョ py o
+ピュ py u
+ピャ py a
+ピェ py e
+ピ p i
+ビョ by o
+ビュ by u
+ビャ by a
+ビェ by e
+ビ b i
+ヒョ hy o
+ヒュ hy u
+ヒャ hy a
+ヒェ hy e
+ヒ h i
+パ p a
+バ b a
+ハ h a
+ノ n o
+ネ n e
+ヌ n u
+ニョ ny o
+ニュ ny u
+ニャ ny a
+ニェ ny e
+ニ n i
+ナ n a
+ドゥ d u
+ド d o
+トゥ t u
+ト t o
+デョ dy o
+デュ dy u
+デャ dy a
+デェ dy e
+ディ d i
+デ d e
+テョ ty o
+テュ ty u
+テャ ty a
+ティ t i
+テ t e
+ヅ z u
+ツォ ts o
+ツェ ts e
+ツィ ts i
+ツァ ts a
+ツ ts u
+ッ cl
+ヂ j i
+チョ ch o
+チュ ch u
+チャ ch a
+チェ ch e
+チ ch i
+ダ d a
+タ t a
+ゾ z o
+ソ s o
+ゼ z e
+セ s e
+ズィ z i
+ズ z u
+スィ s i
+ス s u
+ジョ j o
+ジュ j u
+ジャ j a
+ジェ j e
+ジ j i
+ショ sh o
+シュ sh u
+シャ sh a
+シェ sh e
+シィ s i
+シ sh i
+ザ z a
+サ s a
+ゴ g o
+コ k o
+ゲ g e
+ケ k e
+グ g u
+ク k u
+ギョ gy o
+ギュ gy u
+ギャ gy a
+ギェ gy e
+ギ g i
+キョ ky o
+キュ ky u
+キャ ky a
+キェ ky e
+キ k i
+ガ g a
+カ k a
+オ o
+ォ o
+エ e
+ェ e
+ウォ w o
+ウェ w e
+ウィ w i
+ウ u
+ゥ u
+イェ y e
+イ i
+ィ i
+ア a
+ァ a
diff --git a/pysinsy/htsvoice/COPYING b/pysinsy/htsvoice/COPYING
new file mode 100644
index 0000000..1fe65f3
--- /dev/null
+++ b/pysinsy/htsvoice/COPYING
@@ -0,0 +1,41 @@
+# ----------------------------------------------------------------- #
+#           The Nitech Japanese Speech Database "NIT SONG070 F001"  #
+#           released by HTS Working Group                           #
+#           http://hts.sp.nitech.ac.jp/                             #
+# ----------------------------------------------------------------- #
+#                                                                   #
+#  Copyright (c) 2004-2015  Nagoya Institute of Technology          #
+#                           Department of Computer Science          #
+#                                                                   #
+# Some rights reserved.                                             #
+#                                                                   #
+# This work is licensed under the Creative Commons Attribution 3.0  #
+# license.                                                          #
+#                                                                   #
+# You are free:                                                     #
+#  * to Share - to copy, distribute and transmit the work           #
+#  * to Remix - to adapt the work                                   #
+# Under the following conditions:                                   #
+#  * Attribution - You must attribute the work in the manner        #
+#    specified by the author or licensor (but not in any way that   #
+#    suggests that they endorse you or your use of the work).       #
+# With the understanding that:                                      #
+#  * Waiver - Any of the above conditions can be waived if you get  #
+#    permission from the copyright holder.                          #
+#  * Public Domain - Where the work or any of its elements is in    #
+#    the public domain under applicable law, that status is in no   #
+#    way affected by the license.                                   #
+#  * Other Rights - In no way are any of the following rights       #
+#    affected by the license:                                       #
+#     - Your fair dealing or fair use rights, or other applicable   #
+#       copyright exceptions and limitations;                       #
+#     - The author's moral rights;                                  #
+#     - Rights other persons may have either in the work itself or  #
+#       in how the work is used, such as publicity or privacy       #
+#       rights.                                                     #
+#  * Notice - For any reuse or distribution, you must make clear to #
+#    others the license terms of this work. The best way to do this #
+#    is with a link to this web page.                               #
+#                                                                   #
+# See http://creativecommons.org/ for details.                      #
+# ----------------------------------------------------------------- #
diff --git a/pysinsy/htsvoice/nitech_jp_song070_f001.htsvoice b/pysinsy/htsvoice/nitech_jp_song070_f001.htsvoice
new file mode 100644
index 0000000..fd8ba22
Binary files /dev/null and b/pysinsy/htsvoice/nitech_jp_song070_f001.htsvoice differ
diff --git a/pysinsy/sinsy.pyx b/pysinsy/sinsy.pyx
index 70141b8..c8ef2b4 100644
--- a/pysinsy/sinsy.pyx
+++ b/pysinsy/sinsy.pyx
@@ -1,4 +1,3 @@
-# coding: utf-8
 # cython: boundscheck=True, wraparound=True
 # cython: c_string_type=unicode, c_string_encoding=ascii
 
@@ -8,10 +7,12 @@ cimport numpy as np
 np.import_array()
 
 cimport cython
-
+from libcpp.string cimport string
+from libcpp.vector cimport vector
 
 from sinsy cimport sinsy, label_strings
 
+
 cdef class LabelStrings(object):
     cdef label_strings.LabelStrings* ptr
 
@@ -29,18 +30,74 @@ cdef class LabelStrings(object):
         if self.ptr is not NULL:
             del self.ptr
 
+cdef class SynthCondition(object):
+    """Sinsy
+    """
+    cdef sinsy.SynthCondition* ptr
+    cdef vector[double] buffer
+
+    def __cinit__(self):
+        self.ptr = new sinsy.SynthCondition()
+        self.buffer = vector[double]()
+        self._setWaveformBuffer(self.buffer)
+
+    def setPlayFlag(self):
+        self.ptr.setPlayFlag()
+
+    def unsetPlayFlag(self):
+        self.ptr.unsetPlayFlag()
+
+    def setSaveFilePath(self, s):
+        cdef string ss = s
+        self.ptr.setSaveFilePath(ss)
+
+    def unsetSaveFilePath(self):
+        self.ptr.unsetSaveFilePath()
+
+    cdef _setWaveformBuffer(self, vector[double]& x):
+        self.ptr.setWaveformBuffer(x)
+
+    def getWaveformBuffer(self):
+        cdef np.ndarray waveform = np.zeros([self.buffer.size()], dtype=np.float64)
+        waveform[:] = self.buffer[:]
+        self.buffer.clear()
+        return waveform
+
+    def __dealloc__(self):
+        del self.ptr
+
 
 cdef class Sinsy(object):
     """Sinsy
+
+    The core Sinsy class
     """
     cdef sinsy.Sinsy* ptr
 
     def __cinit__(self):
         self.ptr = new sinsy.Sinsy()
 
-    def setLanguages(self, lang="j", config="/usr/local/lib/sinsy/dic"):
+    def setLanguages(self, lang, config):
+        """Set language
+
+        Args:
+            lang (str): language code.
+            config (str): Path to dictionary.
+        """
         return self.ptr.setLanguages(lang, config)
 
+    def loadVoices(self, voice):
+        """Load hts voice
+
+        Args:
+            voice (str): Path to hts voice.
+        """
+        cdef vector[string] voices
+        voices.push_back(voice)
+        cdef char ret
+        ret = self.ptr.loadVoices(voices)
+        return ret
+
     def setAlpha(self, alpha):
         return self.ptr.setAlpha(alpha)
 
@@ -48,17 +105,50 @@ cdef class Sinsy(object):
         return self.ptr.setVolume(alpha)
 
     def createLabelData(self, monophoneFlag=False, overwriteEnableFlag=1, timeFlag=1):
-        cdef label_strings.LabelStrings* p 
+        cdef label_strings.LabelStrings* p
         p = self.ptr.createLabelData(monophoneFlag, overwriteEnableFlag, timeFlag)
         cdef LabelStrings label = LabelStrings()
         label.ptr = p
         return label
-    
+
+    def synthesize(self):
+        """Synthesize waveform
+
+        Returns:
+            wav (ndarray): numpy array of type float64.
+            sr (int): sampling frequency.
+
+        Raises:
+            RuntimeError: if fail to synthesize
+        """
+        cond = SynthCondition()
+        cond.setPlayFlag()
+        ret = self.ptr.synthesize(cond.ptr)
+        if ret == False:
+            raise RuntimeError("Failed to synthesize")
+        wav = cond.getWaveformBuffer()
+        sr = self.get_sampling_frequency()
+        return wav, sr
+
     def clearScore(self):
+        """Clear loaded score"""
         self.ptr.clearScore()
-    
+
     def loadScoreFromMusicXML(self, xml):
+        """Load score from music xml
+
+        Args:
+            xml (str): Path to music xml.
+        """
         return self.ptr.loadScoreFromMusicXML(xml)
-        
+
+    def get_sampling_frequency(self):
+        """Get sampling frequency
+
+        Returns:
+            int: sampling rate.
+        """
+        return self.ptr.get_sampling_frequency()
+
     def __dealloc__(self):
         del self.ptr
diff --git a/pysinsy/sinsy/label_strings.pxd b/pysinsy/sinsy/label_strings.pxd
index 0b53fed..86f5785 100644
--- a/pysinsy/sinsy/label_strings.pxd
+++ b/pysinsy/sinsy/label_strings.pxd
@@ -4,7 +4,7 @@ from libcpp cimport bool
 from libcpp.string cimport string
 from libcpp.vector import vector
 
-cdef extern from "sinsy/LabelStrings.h" namespace "sinsy":
+cdef extern from "LabelStrings.h" namespace "sinsy":
     cdef cppclass LabelStrings:
       void LabelStrings()
       size_t size()
diff --git a/pysinsy/sinsy/sinsy.pxd b/pysinsy/sinsy/sinsy.pxd
index fe07830..609e8a5 100644
--- a/pysinsy/sinsy/sinsy.pxd
+++ b/pysinsy/sinsy/sinsy.pxd
@@ -6,9 +6,16 @@ from libcpp.vector cimport vector
 
 from .label_strings cimport LabelStrings
 
-cdef extern from "sinsy/sinsy.h" namespace "sinsy":
+cdef extern from "sinsy.h" namespace "sinsy":
    cdef cppclass SynthCondition:
       SynthCondition()
+      void setPlayFlag()
+      void unsetPlayFlag()
+      void setSaveFilePath(const string& filePath)
+      void unsetSaveFilePath()
+      void setWaveformBuffer(vector[double]& waveform)
+      void unsetWaveformBuffer()
+
 
    cdef cppclass Sinsy:
       Sinsy()
@@ -20,9 +27,11 @@ cdef extern from "sinsy/sinsy.h" namespace "sinsy":
 
       LabelStrings* createLabelData(bool monophoneFlag, int overwriteEnableFlag, int timeFlag)
 
-      bool synthesize(SynthCondition& condition)
+      bool synthesize(SynthCondition* condition)
       bool stop()
       bool resetStopFlag()
       bool clearScore()
 
-      bool loadScoreFromMusicXML(const string& xml)
\ No newline at end of file
+      bool loadScoreFromMusicXML(const string& xml)
+
+      size_t get_sampling_frequency()
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 9047f10..58dfdc9 100644
--- a/setup.py
+++ b/setup.py
@@ -1,79 +1,97 @@
-# coding: utf-8
-
-from __future__ import with_statement, print_function, absolute_import
-
-from setuptools import setup, find_packages, Extension
-import setuptools.command.develop
-import setuptools.command.build_py
-from distutils.version import LooseVersion
-import subprocess
-import numpy as np
 import os
+import subprocess
+import sys
+from distutils.version import LooseVersion
+from glob import glob
 from os.path import join
 
-version = '0.0.1'
-
-sinsy_install_prefix = os.environ.get(
-    "SINSY_INSTALL_PREFIX", "/usr/local/")
+import numpy as np
+import setuptools.command.build_py
+import setuptools.command.develop
+from setuptools import Extension, find_packages, setup
 
-sinsy_include_top = join(sinsy_install_prefix, "include")
-sinsy_library_path = join(sinsy_install_prefix, "lib")
+platform_is_windows = sys.platform == "win32"
 
-lib_candidates = list(filter(lambda l: l.startswith("libsinsy."),
-                             os.listdir(join(sinsy_library_path))))
-if len(lib_candidates) == 0:
-    raise OSError("sinsy library cannot be found")
+version = "0.0.1"
 
-min_cython_ver = '0.21.0'
+min_cython_ver = "0.21.0"
 try:
     import Cython
+
     ver = Cython.__version__
     _CYTHON_INSTALLED = ver >= LooseVersion(min_cython_ver)
 except ImportError:
     _CYTHON_INSTALLED = False
 
+
 try:
     if not _CYTHON_INSTALLED:
-        raise ImportError('No supported version of Cython installed.')
+        raise ImportError("No supported version of Cython installed.")
     from Cython.Distutils import build_ext
-    from Cython.Build import cythonize
+
     cython = True
 except ImportError:
     cython = False
 
 if cython:
-    ext = '.pyx'
-    cmdclass = {'build_ext': build_ext}
+    ext = ".pyx"
+    cmdclass = {"build_ext": build_ext}
 else:
-    ext = '.cpp'
+    ext = ".cpp"
     cmdclass = {}
     if not os.path.exists(join("pysinsy", "sinsy" + ext)):
         raise RuntimeError("Cython is required to generate C++ code")
 
-ext_modules = cythonize(
-    [Extension(
+
+# sinsy sources
+src_top = join("lib", "sinsy", "src")
+
+all_src = []
+include_dirs = []
+for s in [
+    "lib",
+    "lib/converter",
+    "lib/japanese",
+    "lib/label",
+    "lib/score",
+    "lib/temporary",
+    "lib/util",
+    "lib/xml",
+    "lib/hts_engine_API",
+    "lib/hts_engine_API/hts_engine/src/lib",
+]:
+    all_src += glob(join(src_top, s, "*.c"))
+    all_src += glob(join(src_top, s, "*.cpp"))
+    include_dirs.append(join(os.getcwd(), src_top, s))
+# Add top include dir
+include_dirs.append(join(src_top, "include", "sinsy"))
+include_dirs.append(join(src_top, "lib/hts_engine_API/hts_engine/src/include"))
+
+# Extension for sinsy
+ext_modules = [
+    Extension(
         name="pysinsy.sinsy",
-        sources=[
-            join("pysinsy", "sinsy" + ext),
-        ],
-        include_dirs=[np.get_include(),
-                      join(sinsy_include_top)],
-        library_dirs=[sinsy_library_path],
-        libraries=["sinsy"],
+        sources=[join("pysinsy", "sinsy" + ext)] + all_src,
+        include_dirs=[np.get_include()] + include_dirs,
         extra_compile_args=[],
         extra_link_args=[],
-        language="c++")],
-)
+        libraries=["winmm"] if platform_is_windows else [],
+        language="c++",
+    )
+]
 
 # Adapted from https://github.com/pytorch/pytorch
 cwd = os.path.dirname(os.path.abspath(__file__))
-if os.getenv('PYSINSY_BUILD_VERSION'):
-    version = os.getenv('PYSINSY_BUILD_VERSION')
+if os.getenv("PYSINSY_BUILD_VERSION"):
+    version = os.getenv("PYSINSY_BUILD_VERSION")
 else:
     try:
-        sha = subprocess.check_output(
-            ['git', 'rev-parse', 'HEAD'], cwd=cwd).decode('ascii').strip()
-        version += '+' + sha[:7]
+        sha = (
+            subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=cwd)
+            .decode("ascii")
+            .strip()
+        )
+        version += "+" + sha[:7]
     except subprocess.CalledProcessError:
         pass
     except IOError:  # FileNotFoundError for python 3
@@ -81,7 +99,6 @@
 
 
 class build_py(setuptools.command.build_py.build_py):
-
     def run(self):
         self.create_version_file()
         setuptools.command.build_py.build_py.run(self)
@@ -89,49 +106,64 @@ def run(self):
     @staticmethod
     def create_version_file():
         global version, cwd
-        print('-- Building version ' + version)
-        version_path = os.path.join(cwd, 'pysinsy', 'version.py')
-        with open(version_path, 'w') as f:
+        print("-- Building version " + version)
+        version_path = os.path.join(cwd, "pysinsy", "version.py")
+        with open(version_path, "w") as f:
             f.write("__version__ = '{}'\n".format(version))
 
 
 class develop(setuptools.command.develop.develop):
-
     def run(self):
         build_py.create_version_file()
         setuptools.command.develop.develop.run(self)
 
 
-cmdclass['build_py'] = build_py
-cmdclass['develop'] = develop
+cmdclass["build_py"] = build_py
+cmdclass["develop"] = develop
 
 
-with open('README.md', 'r') as fd:
+with open("README.md", "r") as fd:
     long_description = fd.read()
 
 setup(
-    name='pysinsy',
+    name="pysinsy",
     version=version,
-    description='A python wrapper for sinsy',
+    description="A python wrapper for sinsy",
     long_description=long_description,
-    long_description_content_type='text/markdown',
-    author='Ryuichi Yamamoto',
-    author_email='zryuichi@gmail.com',
-    url='https://github.com/r9y9/pysinsy',
-    license='MIT',
+    long_description_content_type="text/markdown",
+    author="Ryuichi Yamamoto",
+    author_email="zryuichi@gmail.com",
+    url="https://github.com/r9y9/pysinsy",
+    license="MIT",
     packages=find_packages(),
-    package_data={'': ['htsvoice/*']},
+    package_data={"": ["htsvoice/*"]},
     ext_modules=ext_modules,
     cmdclass=cmdclass,
     install_requires=[
-        'numpy >= 1.8.0',
-        'cython >= ' + min_cython_ver,
-        'six',
+        "numpy >= 1.8.0",
+        "cython >= " + min_cython_ver,
+        "six",
     ],
-    tests_require=['nose', 'coverage'],
+    tests_require=["pytest", "coverage"],
     extras_require={
-        'docs': ['sphinx_rtd_theme'],
-        'test': ['nose', 'scipy'],
+        "docs": [
+            "sphinx_rtd_theme",
+            "nbsphinx>=0.8.6",
+            "Jinja2>=3.0.1",
+            "pandoc",
+            "ipython",
+            "jupyter",
+        ],
+        "lint": [
+            "pysen",
+            "types-setuptools",
+            "mypy<=0.910",
+            "black>=19.19b0,<=20.8",
+            "flake8>=3.7,<4",
+            "flake8-bugbear",
+            "isort>=4.3,<5.2.0",
+        ],
+        "test": ["pytest", "scipy"],
     },
     classifiers=[
         "Operating System :: POSIX",
@@ -140,15 +172,14 @@ def run(self):
         "Programming Language :: Cython",
         "Programming Language :: Python",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.5",
-        "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
         "License :: OSI Approved :: MIT License",
         "Topic :: Scientific/Engineering",
         "Topic :: Software Development",
         "Intended Audience :: Science/Research",
         "Intended Audience :: Developers",
     ],
-    keywords=["Sinsy", "Research"]
+    keywords=["Sinsy", "Research"],
 )


Test patch:
diff --git a/tests/test_pysinsy.py b/tests/test_pysinsy.py
index 41dff99..23a3ab0 100644
--- a/tests/test_pysinsy.py
+++ b/tests/test_pysinsy.py
@@ -1,25 +1,48 @@
 # coding: utf-8
 
 from os.path import dirname, join
-import pysinsy
 
+import pysinsy
 
 DATA_DIR = dirname(__file__)
 
 
-def test_pysinsy():
+def test_pysinsy_frontend():
     # http://sinsy.sp.nitech.ac.jp/sample/song070_f00001_063.xml
 
     xml_path = join(DATA_DIR, "song070_f00001_063.xml")
 
     sinsy = pysinsy.sinsy.Sinsy()
-    assert sinsy.setLanguages("j", "/usr/local/lib/sinsy/dic")
+    assert sinsy.setLanguages("j", pysinsy.get_default_dic_dir())
     assert sinsy.loadScoreFromMusicXML(xml_path)
 
-    is_mono = True
     for is_mono in [True, False]:
         label = sinsy.createLabelData(is_mono, 1, 1)
-        for l in label.getData():
-            print(l)
+        for line in label.getData():
+            print(line)
 
     sinsy.clearScore()
+
+
+def test_pysinsy_synthesize():
+    xml_path = join(DATA_DIR, "song070_f00001_063.xml")
+
+    sinsy = pysinsy.sinsy.Sinsy()
+    assert sinsy.setLanguages("j", pysinsy.get_default_dic_dir())
+    assert sinsy.loadScoreFromMusicXML(xml_path)
+    assert sinsy.loadVoices(pysinsy.get_default_htsvoice())
+
+    wav, sr = sinsy.synthesize()
+    assert len(wav) > 0 and wav.max() > 0
+    assert sr == 48000
+
+    sinsy.clearScore()
+
+
+def test_pysinsy_highlevel():
+    xml_path = join(DATA_DIR, "song070_f00001_063.xml")
+
+    for _ in range(3):
+        wav, sr = pysinsy.synthesize(xml_path)
+        assert len(wav) > 0 and wav.max() > 0
+        assert sr == 48000