├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── app-release.apk
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── io
│ │ └── github
│ │ └── junyuecao
│ │ └── androidsoundeffect
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── io
│ │ │ └── github
│ │ │ └── junyuecao
│ │ │ └── androidsoundeffect
│ │ │ ├── MainActivity.kt
│ │ │ └── VoiceRecorder.java
│ └── res
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── io
│ └── github
│ └── junyuecao
│ └── androidsoundeffect
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── soundtouch
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── io
│ └── github
│ └── junyuecao
│ └── soundtouch
│ └── ExampleInstrumentedTest.java
├── main
├── AndroidManifest.xml
├── cpp
│ ├── Android.mk
│ ├── Application.mk
│ ├── SoundTouch
│ │ ├── AAFilter.cpp
│ │ ├── AAFilter.h
│ │ ├── BPMDetect.cpp
│ │ ├── FIFOSampleBuffer.cpp
│ │ ├── FIRFilter.cpp
│ │ ├── FIRFilter.h
│ │ ├── InterpolateCubic.cpp
│ │ ├── InterpolateCubic.h
│ │ ├── InterpolateLinear.cpp
│ │ ├── InterpolateLinear.h
│ │ ├── InterpolateShannon.cpp
│ │ ├── InterpolateShannon.h
│ │ ├── Makefile.am
│ │ ├── PeakFinder.cpp
│ │ ├── PeakFinder.h
│ │ ├── RateTransposer.cpp
│ │ ├── RateTransposer.h
│ │ ├── SoundTouch.cpp
│ │ ├── SoundTouch.dsp
│ │ ├── SoundTouch.dsw
│ │ ├── SoundTouch.sln
│ │ ├── SoundTouch.vcproj
│ │ ├── TDStretch.cpp
│ │ ├── TDStretch.h
│ │ ├── cpu_detect.h
│ │ ├── cpu_detect_x86.cpp
│ │ ├── include
│ │ │ ├── BPMDetect.h
│ │ │ ├── FIFOSampleBuffer.h
│ │ │ ├── FIFOSamplePipe.h
│ │ │ ├── Makefile.am
│ │ │ ├── STTypes.h
│ │ │ ├── SoundTouch.h
│ │ │ └── soundtouch_config.h.in
│ │ ├── mmx_optimized.cpp
│ │ └── sse_optimized.cpp
│ ├── SoundTouchJNI.cpp
│ └── common.h
├── java
│ └── io
│ │ └── github
│ │ └── junyuecao
│ │ └── soundtouch
│ │ └── SoundTouch.java
└── res
│ └── values
│ └── strings.xml
└── test
└── java
└── io
└── github
└── junyuecao
└── soundtouch
└── ExampleUnitTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | android:
3 | components:
4 | - build-tools-26.0.1
5 | - android-26
6 | - extra
7 | before_script:
8 | - export TERM=dumb
9 | # Approx. 3 seconds
10 | - curl -L https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip -O
11 | # Usually around 1 minute
12 | - unzip android-ndk-r14b-linux-x86_64.zip > /dev/null
13 | - rm android-ndk-r14b-linux-x86_64.zip
14 | - export ANDROID_NDK_HOME=`pwd`/android-ndk-r14b
15 | - export LOCAL_ANDROID_NDK_HOME="$ANDROID_NDK_HOME"
16 | - export LOCAL_ANDROID_NDK_HOST_PLATFORM="linux-x86_64"
17 | - export PATH=$PATH:${ANDROID_NDK_HOME}
18 | - env
19 | script:
20 | - ./gradlew build
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidSoundTouch
2 | [](https://travis-ci.org/junyuecao/AndroidSoundTouch)
3 |
4 | A handy SoundTouch java wrapper library for Android
5 |
6 | This repo is a java wrapper of [SoundTouch](https://www.surina.net/soundtouch/) for Android.
7 |
8 | - Keep APIs of soundtouch and provide a Java class to process audio streams so you can do it without any C/C++ code.
9 | - Support ENCODING_PCM_16BIT samples.
10 | - Support mono(1)/stereo(2) channels.
11 | - Support short/byte array input/output
12 |
13 | ## Demo
14 |
15 | [Demo apk download link](https://github.com/junyuecao/AndroidSoundTouch/blob/master/app-release.apk?raw=true)
16 |
17 | Note: You should grant audio record permission manually before using.
18 |
19 | ## Usage
20 | Gradle:
21 | ```groovy
22 | repositories {
23 | jcenter()
24 | }
25 |
26 | // For gradle plugin 2.x
27 | dependencies {
28 | compile 'io.github.junyuecao:soundtouch:1.0.1'
29 | }
30 |
31 | // For gradle plugin 3.x
32 | dependencies {
33 | implementation 'io.github.junyuecao:soundtouch:1.0.1'
34 | }
35 | ```
36 |
37 | The APIs are almost the same with the C/C++ version.
38 | - in Java
39 | ```Java
40 | public void onVoiceStart() {
41 | mSoundTouch = new SoundTouch();
42 | mSoundTouch.setChannels(1);
43 | mSoundTouch.setSampleRate(VoiceRecorder.SAMPLE_RATE);
44 | }
45 |
46 | public void onVoice(byte[] data, int size) {
47 | mSoundTouch.setRate(mRate);
48 | mSoundTouch.setPitch(mPitch);
49 | mSoundTouch.putSamples(data, size);
50 | int bufferSize = 0
51 | do {
52 | bufferSize = mSoundTouch.receiveSamples(mTempBuffer, BUFFER_SIZE);
53 | if (bufferSize > 0) {
54 | mTestWavOutput.write(mTempBuffer, 0, bufferSize);
55 | }
56 | } while (bufferSize != 0);
57 |
58 | }
59 |
60 | public void onVoiceEnd() {
61 | mSoundTouch.release();
62 | }
63 | ```
64 |
65 |
--------------------------------------------------------------------------------
/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app-release.apk
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | def sign = project.hasProperty("RELEASE_STORE_FILE");
9 | signingConfigs {
10 | if (sign) {
11 | myConfig {
12 | //需要在build.gradle同目录下的gradle.properties中配置以下信息
13 | //RELEASE_STORE_FILE=/path/to/key/
14 | //RELEASE_STORE_PASSWORD=***********
15 | //RELEASE_KEY_ALIAS=*****
16 | //RELEASE_KEY_PASSWORD=*******
17 | storeFile file(RELEASE_STORE_FILE)
18 | storePassword RELEASE_STORE_PASSWORD
19 | keyAlias RELEASE_KEY_ALIAS
20 | keyPassword RELEASE_KEY_PASSWORD
21 | }
22 | }
23 |
24 | }
25 | compileSdkVersion 26
26 | buildToolsVersion "26.0.1"
27 | defaultConfig {
28 | applicationId "io.github.junyuecao.androidsoundeffect"
29 | minSdkVersion 21
30 | targetSdkVersion 26
31 | versionCode 1
32 | versionName "1.0"
33 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
34 | }
35 | buildTypes {
36 | release {
37 | signingConfig sign ? signingConfigs.myConfig : null
38 | minifyEnabled false
39 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
40 | }
41 | }
42 | }
43 |
44 | dependencies {
45 | implementation fileTree(dir: 'libs', include: ['*.jar'])
46 | implementation 'com.android.support:appcompat-v7:26.1.0'
47 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
48 | testImplementation 'junit:junit:4.12'
49 | androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
50 | exclude group: 'com.android.support', module: 'support-annotations'
51 | })
52 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
53 | compile project(path: ':soundtouch')
54 | }
55 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/io/github/junyuecao/androidsoundeffect/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package io.github.junyuecao.androidsoundeffect
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("io.github.junyuecao.androidsoundeffect", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/junyuecao/androidsoundeffect/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package io.github.junyuecao.androidsoundeffect
2 |
3 | import android.media.AudioFormat
4 | import android.media.MediaPlayer
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import android.support.v7.app.AppCompatActivity
8 | import android.util.Log
9 | import android.widget.SeekBar
10 | import io.github.junyuecao.soundtouch.SoundTouch
11 | import kotlinx.android.synthetic.main.activity_main.*
12 | import java.io.*
13 | import java.nio.ByteBuffer
14 | import java.nio.ByteOrder
15 |
16 |
17 | class MainActivity : AppCompatActivity(), VoiceRecorder.Callback {
18 | val TAG = "MainActivity"
19 | private var mRecorder : VoiceRecorder? = null
20 | private var mSoundTouch : SoundTouch? = null
21 | private var mIsRecording = false
22 | private var mTestWavOutput: FileOutputStream? = null
23 | private val BUFFER_SIZE: Int = 4096
24 | private var mTempBuffer : ByteArray = ByteArray(BUFFER_SIZE)
25 |
26 | private var mPitch: Double = 1.0;
27 | private var mRate: Double = 1.0;
28 |
29 | override fun onVoiceStart() {
30 | mSoundTouch = SoundTouch()
31 | mSoundTouch?.setChannels(1)
32 | mSoundTouch?.setSampleRate(VoiceRecorder.SAMPLE_RATE)
33 | mTestWavOutput = getTestWavOutput()
34 | writeWavHeader(mTestWavOutput!!,
35 | AudioFormat.CHANNEL_IN_MONO,
36 | VoiceRecorder.SAMPLE_RATE,
37 | AudioFormat.ENCODING_PCM_16BIT);
38 | }
39 |
40 | override fun onVoice(data: ByteArray?, size: Int) {
41 | Log.d(TAG, "onVoice: $data, Size: $size")
42 | mSoundTouch?.setRate(mRate)
43 | mSoundTouch?.setPitch(mPitch)
44 | mSoundTouch?.putSamples(data, size)
45 | var bufferSize = 0
46 | do {
47 | bufferSize = mSoundTouch!!.receiveSamples(mTempBuffer, BUFFER_SIZE)
48 | if (bufferSize > 0) {
49 | mTestWavOutput?.write(mTempBuffer, 0, bufferSize)
50 | }
51 | } while (bufferSize != 0)
52 |
53 | }
54 |
55 | override fun onVoiceEnd() {
56 | mSoundTouch?.release()
57 | try {
58 | mTestWavOutput?.close()
59 | mTestWavOutput = null
60 | } catch (e: IOException) {
61 | e.printStackTrace()
62 | }
63 | updateWavHeader(getTempFile())
64 | }
65 |
66 | override fun onCreate(savedInstanceState: Bundle?) {
67 | super.onCreate(savedInstanceState)
68 | setContentView(R.layout.activity_main)
69 |
70 | // Example of a call to a native method
71 | mRecorder = VoiceRecorder(this)
72 |
73 | start.setOnClickListener {
74 | mIsRecording = !mIsRecording
75 | if (mIsRecording) {
76 | start.text = "Stop"
77 | mRecorder?.start()
78 | } else {
79 | start.text = "Start"
80 | mRecorder?.stop()
81 | }
82 |
83 | }
84 |
85 | play.setOnClickListener {
86 | val tempFile = getTempFile()
87 | if (tempFile.exists()) {
88 | val player = MediaPlayer.create(this, Uri.fromFile(tempFile))
89 | player.start()
90 | }
91 | }
92 | pitchText.text = "Pitch: $mPitch"
93 | pitch.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
94 | override fun onStartTrackingTouch(p0: SeekBar?) {
95 |
96 | }
97 |
98 | override fun onStopTrackingTouch(p0: SeekBar?) {
99 |
100 | }
101 |
102 | override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
103 | if (pitch.progress > 500) {
104 | mPitch = (3.0 / 500.0) * pitch.progress - 2
105 | } else{
106 | mPitch = 0.75 / 500 * pitch.progress+ 0.25
107 | }
108 | pitchText.text = "Pitch: $mPitch"
109 | }
110 |
111 | })
112 | rateText.text = "Rate: $mRate"
113 | rate.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
114 | override fun onStartTrackingTouch(p0: SeekBar?) {
115 |
116 | }
117 |
118 | override fun onStopTrackingTouch(p0: SeekBar?) {
119 |
120 | }
121 |
122 | override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
123 | if (pitch.progress > 500) {
124 | mRate = (3.0 / 500.0) * rate.progress - 2
125 | } else{
126 | mRate = 0.75 / 500 * rate.progress+ 0.25
127 | }
128 | rateText.text = "Rate: $mRate"
129 | }
130 | })
131 | }
132 |
133 | private fun getTestWavOutput(): FileOutputStream? {
134 | val s = getTempFile()
135 |
136 | try {
137 | val os = FileOutputStream(s)
138 | return os
139 | } catch (e: FileNotFoundException) {
140 | e.printStackTrace()
141 | return null
142 | }
143 |
144 | }
145 |
146 | override fun onStop() {
147 | super.onStop()
148 | mIsRecording = false
149 | start.text = "Start"
150 | mRecorder?.stop()
151 | }
152 |
153 | private fun getTempFile() = File(getExternalFilesDir(null), "record_temp.wav")
154 |
155 | /**
156 | * Writes the proper 44-byte RIFF/WAVE header to/for the given stream
157 | * Two size fields are left empty/null since we do not yet know the final stream size
158 |
159 | * @param out The stream to write the header to
160 | * *
161 | * @param channelMask An AudioFormat.CHANNEL_* mask
162 | * *
163 | * @param sampleRate The sample rate in hertz
164 | * *
165 | * @param encoding An AudioFormat.ENCODING_PCM_* value
166 | * *
167 | * @throws IOException
168 | */
169 | @Throws(IOException::class)
170 | private fun writeWavHeader(out: OutputStream, channelMask: Int, sampleRate: Int, encoding: Int) {
171 | val channels: Short
172 | when (channelMask) {
173 | AudioFormat.CHANNEL_IN_MONO -> channels = 1
174 | AudioFormat.CHANNEL_IN_STEREO -> channels = 2
175 | else -> throw IllegalArgumentException("Unacceptable channel mask")
176 | }
177 |
178 | val bitDepth: Short
179 | when (encoding) {
180 | AudioFormat.ENCODING_PCM_8BIT -> bitDepth = 8
181 | AudioFormat.ENCODING_PCM_16BIT -> bitDepth = 16
182 | AudioFormat.ENCODING_PCM_FLOAT -> bitDepth = 32
183 | else -> throw IllegalArgumentException("Unacceptable encoding")
184 | }
185 |
186 | writeWavHeader(out, channels, sampleRate, bitDepth)
187 | }
188 |
189 | /**
190 | * Writes the proper 44-byte RIFF/WAVE header to/for the given stream
191 | * Two size fields are left empty/null since we do not yet know the final stream size
192 |
193 | * @param out The stream to write the header to
194 | * *
195 | * @param channels The number of channels
196 | * *
197 | * @param sampleRate The sample rate in hertz
198 | * *
199 | * @param bitDepth The bit depth
200 | * *
201 | * @throws IOException
202 | */
203 | @Throws(IOException::class)
204 | private fun writeWavHeader(out: OutputStream, channels: Short, sampleRate: Int, bitDepth: Short) {
205 | // Convert the multi-byte integers to raw bytes in little endian format as required by the spec
206 | val littleBytes = ByteBuffer
207 | .allocate(14)
208 | .order(ByteOrder.LITTLE_ENDIAN)
209 | .putShort(channels)
210 | .putInt(sampleRate)
211 | .putInt(sampleRate * channels.toInt() * (bitDepth / 8))
212 | .putShort((channels * (bitDepth / 8)).toShort())
213 | .putShort(bitDepth)
214 | .array()
215 |
216 | // Not necessarily the best, but it's very easy to visualize this way
217 | out.write(byteArrayOf(
218 | // RIFF header
219 | 'R'.toByte(), 'I'.toByte(), 'F'.toByte(), 'F'.toByte(), // ChunkID
220 | 0, 0, 0, 0, // ChunkSize (must be updated later)
221 | 'W'.toByte(), 'A'.toByte(), 'V'.toByte(), 'E'.toByte(), // Format
222 | // fmt subchunk
223 | 'f'.toByte(), 'm'.toByte(), 't'.toByte(), ' '.toByte(), // Subchunk1ID
224 | 16, 0, 0, 0, // Subchunk1Size
225 | 1, 0, // AudioFormat
226 | littleBytes[0], littleBytes[1], // NumChannels
227 | littleBytes[2], littleBytes[3], littleBytes[4], littleBytes[5], // SampleRate
228 | littleBytes[6], littleBytes[7], littleBytes[8], littleBytes[9], // ByteRate
229 | littleBytes[10], littleBytes[11], // BlockAlign
230 | littleBytes[12], littleBytes[13], // BitsPerSample
231 | // data subchunk
232 | 'd'.toByte(), 'a'.toByte(), 't'.toByte(), 'a'.toByte(), // Subchunk2ID
233 | 0, 0, 0, 0)// Subchunk2Size (must be updated later)
234 | )
235 | }
236 |
237 | /**
238 | * Updates the given wav file's header to include the final chunk sizes
239 |
240 | * @param wav The wav file to update
241 | * *
242 | * @throws IOException
243 | */
244 | @Throws(IOException::class)
245 | private fun updateWavHeader(wav: File) {
246 | val sizes = ByteBuffer
247 | .allocate(8)
248 | .order(ByteOrder.LITTLE_ENDIAN)
249 | // There are probably a bunch of different/better ways to calculate
250 | // these two given your circumstances. Cast should be safe since if the WAV is
251 | // > 4 GB we've already made a terrible mistake.
252 | .putInt((wav.length() - 8).toInt()) // ChunkSize
253 | .putInt((wav.length() - 44).toInt()) // Subchunk2Size
254 | .array()
255 |
256 | var accessWave: RandomAccessFile? = null
257 |
258 | try {
259 | accessWave = RandomAccessFile(wav, "rw")
260 | // ChunkSize
261 | accessWave.seek(4)
262 | accessWave.write(sizes, 0, 4)
263 |
264 | // Subchunk2Size
265 | accessWave.seek(40)
266 | accessWave.write(sizes, 4, 4)
267 | } catch (ex: IOException) {
268 | // Rethrow but we still close accessWave in our finally
269 | throw ex
270 | } finally {
271 | if (accessWave != null) {
272 | try {
273 | accessWave.close()
274 | } catch (ex: IOException) {
275 | //
276 | }
277 |
278 | }
279 | }
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/junyuecao/androidsoundeffect/VoiceRecorder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Google Inc. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package io.github.junyuecao.androidsoundeffect;
18 |
19 | import android.media.AudioFormat;
20 | import android.media.AudioRecord;
21 | import android.media.MediaRecorder;
22 | import android.support.annotation.NonNull;
23 | import android.support.annotation.RequiresApi;
24 |
25 | /**
26 | * 麦克风采集
27 | * Continuously records audio and notifies the {@link VoiceRecorder.Callback} when voice (or any
28 | * sound) is heard.
29 | *
30 | *
The recorded audio format is always {@link AudioFormat#ENCODING_PCM_16BIT} and
31 | * {@link AudioFormat#CHANNEL_IN_MONO}. This class will automatically pick the right sample rate
32 | * for the device. Use {@link #getSampleRate()} to get the selected value.
33 | */
34 | @RequiresApi(18)
35 | public class VoiceRecorder {
36 |
37 | public static final int SAMPLE_RATE = 44100;
38 |
39 | private static final int CHANNEL = AudioFormat.CHANNEL_IN_MONO;
40 | private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT;
41 |
42 | // private static final int AMPLITUDE_THRESHOLD = 1500;
43 | // private static final int SPEECH_TIMEOUT_MILLIS = 2000;
44 | private static final int MAX_SPEECH_LENGTH_MILLIS = 30 * 1000;
45 | private final Callback mCallback;
46 | private final Object mLock = new Object();
47 | private AudioRecord mAudioRecord;
48 |
49 | private Thread mThread;
50 |
51 | private byte[] mBuffer;
52 | /** The timestamp of the last time that voice is heard. */
53 | private long mLastVoiceHeardMillis = Long.MAX_VALUE;
54 | /** The timestamp when the current voice is started. */
55 | private long mVoiceStartedMillis;
56 |
57 | public VoiceRecorder(@NonNull Callback callback) {
58 | mCallback = callback;
59 | }
60 |
61 | /**
62 | * Starts recording audio.
63 | *
64 | *
The caller is responsible for calling {@link #stop()} later.
65 | */
66 | public void start() {
67 | // Stop recording if it is currently ongoing.
68 | stop();
69 | // Try to create a new recording session.
70 | mAudioRecord = createAudioRecord();
71 | if (mAudioRecord == null) {
72 | throw new RuntimeException("Cannot instantiate VoiceRecorder");
73 | }
74 | // Start recording.
75 | mAudioRecord.startRecording();
76 | // Start processing the captured audio.
77 | mThread = new Thread(new ProcessVoice());
78 | mThread.start();
79 | }
80 |
81 | /**
82 | * Stops recording audio.
83 | */
84 | public void stop() {
85 | if (mThread != null) {
86 | mThread.interrupt();
87 | mThread = null;
88 | }
89 | synchronized (mLock) {
90 | dismiss();
91 | if (mAudioRecord != null) {
92 | mAudioRecord.stop();
93 | mAudioRecord.release();
94 | mAudioRecord = null;
95 | }
96 | mBuffer = null;
97 | }
98 | }
99 |
100 | /**
101 | * Dismisses the currently ongoing utterance.
102 | */
103 | public void dismiss() {
104 | if (mLastVoiceHeardMillis != Long.MAX_VALUE) {
105 | mLastVoiceHeardMillis = Long.MAX_VALUE;
106 | mCallback.onVoiceEnd();
107 | }
108 | }
109 |
110 | /**
111 | * Retrieves the sample rate currently used to record audio.
112 | *
113 | * @return The sample rate of recorded audio.
114 | */
115 | public int getSampleRate() {
116 | if (mAudioRecord != null) {
117 | return mAudioRecord.getSampleRate();
118 | }
119 | return 0;
120 | }
121 |
122 | /**
123 | * Creates a new {@link AudioRecord}.
124 | *
125 | * @return A newly created {@link AudioRecord}, or null if it cannot be created (missing
126 | * permissions?).
127 | */
128 | private AudioRecord createAudioRecord() {
129 | // for (int sampleRate : SAMPLE_RATE_CANDIDATES) {
130 | final int sizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL, ENCODING);
131 | if (sizeInBytes == AudioRecord.ERROR_BAD_VALUE) {
132 | return null;
133 | }
134 | final AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
135 | SAMPLE_RATE, CHANNEL, ENCODING, sizeInBytes);
136 | if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
137 | mBuffer = new byte[sizeInBytes];
138 | return audioRecord;
139 | } else {
140 | audioRecord.release();
141 | }
142 | // }
143 | return null;
144 | }
145 |
146 | public static abstract interface Callback {
147 |
148 | /**
149 | * Called when the recorder starts hearing voice.
150 | */
151 | void onVoiceStart();
152 |
153 | /**
154 | * Called when the recorder is hearing voice.
155 | *
156 | * @param data The audio data in {@link AudioFormat#ENCODING_PCM_16BIT}.
157 | * @param size The size of the actual data in {@code data}.
158 | */
159 | void onVoice(byte[] data, int size);
160 |
161 | /**
162 | * Called when the recorder stops hearing voice.
163 | */
164 | void onVoiceEnd();
165 | }
166 |
167 | /**
168 | * Continuously processes the captured audio and notifies {@link #mCallback} of corresponding
169 | * events.
170 | */
171 | private class ProcessVoice implements Runnable {
172 |
173 | @Override
174 | public void run() {
175 | while (true) {
176 | synchronized (mLock) {
177 | if (Thread.currentThread().isInterrupted()) {
178 | break;
179 | }
180 | if(mAudioRecord == null)
181 | continue;
182 | if(mBuffer == null)
183 | continue;
184 | final int size = mAudioRecord.read(mBuffer, 0, mBuffer.length);
185 | final long now = System.currentTimeMillis();
186 | if (mLastVoiceHeardMillis == Long.MAX_VALUE) {
187 | mVoiceStartedMillis = now;
188 | mCallback.onVoiceStart();
189 | }
190 | mCallback.onVoice(mBuffer, size);
191 | mLastVoiceHeardMillis = now;
192 | if (now - mVoiceStartedMillis > MAX_SPEECH_LENGTH_MILLIS) {
193 | end();
194 | }
195 |
196 | }
197 | }
198 | }
199 |
200 | private void end() {
201 | mLastVoiceHeardMillis = Long.MAX_VALUE;
202 | mCallback.onVoiceEnd();
203 | }
204 |
205 | }
206 |
207 | }
208 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
17 |
22 |
27 |
32 |
37 |
42 |
47 |
52 |
57 |
62 |
67 |
72 |
77 |
82 |
87 |
92 |
97 |
102 |
107 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
22 |
23 |
34 |
35 |
46 |
47 |
58 |
59 |
70 |
71 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AndroidSoundEffect
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/io/github/junyuecao/androidsoundeffect/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package io.github.junyuecao.androidsoundeffect
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.1.3-2'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.0.0-beta6'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
13 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
14 |
15 | // NOTE: Do not place your application dependencies here; they belong
16 | // in the individual module build.gradle files
17 | }
18 | }
19 |
20 | allprojects {
21 | repositories {
22 | google()
23 | jcenter()
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Sep 29 10:25:07 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':soundtouch'
2 |
--------------------------------------------------------------------------------
/soundtouch/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/soundtouch/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: 'com.jfrog.bintray'
4 | version = "1.0.1"
5 |
6 | android {
7 | compileSdkVersion 26
8 | buildToolsVersion "26.0.1"
9 |
10 |
11 | defaultConfig {
12 | minSdkVersion 14
13 | targetSdkVersion 26
14 | versionCode 1
15 | versionName "1.0"
16 |
17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
18 |
19 | externalNativeBuild {
20 | ndkBuild {
21 | targets "native-lib"
22 | abiFilters 'arm64-v8a', "armeabi-v7a", "x86"
23 | }
24 | }
25 | }
26 |
27 | buildTypes {
28 | release {
29 | minifyEnabled false
30 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
31 | }
32 | }
33 |
34 | externalNativeBuild {
35 | ndkBuild {
36 | path 'src/main/cpp/Android.mk'
37 | }
38 | }
39 | }
40 |
41 | dependencies {
42 | implementation fileTree(dir: 'libs', include: ['*.jar'])
43 | testImplementation 'junit:junit:4.12'
44 | androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
45 | exclude group: 'com.android.support', module: 'support-annotations'
46 | })
47 |
48 | }
49 |
50 | def siteUrl = 'https://github.com/junyuecao/AndroidSoundTouch' // Home page
51 | def gitUrl = 'https://github.com/junyuecao/AndroidSoundTouch.git' // Git repo
52 |
53 | group = "io.github.junyuecao" // Maven Group ID for the artifact
54 | install {
55 | repositories.mavenInstaller {
56 | // This generates POM.xml with proper parameters
57 | pom {
58 | project {
59 | packaging 'aar'
60 | // Add your description here
61 | name 'A SoundTouch java wrapper library for Android'
62 | url siteUrl
63 | // Set your license
64 | licenses {
65 | license {
66 | name 'GNU Lesser General Public License v3.0'
67 | url 'https://www.gnu.org/licenses/lgpl-3.0.en.html'
68 | }
69 | }
70 | developers {
71 | developer {
72 | id 'junyuecao' //填写开发者基本信息
73 | name 'junyuecao'
74 | email 'junyuecao@gmail.com'
75 | }
76 | }
77 | scm {
78 | connection gitUrl
79 | developerConnection gitUrl
80 | url siteUrl
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
87 |
88 | task sourcesJar(type: Jar) {
89 | from android.sourceSets.main.java.srcDirs
90 | classifier = 'sources'
91 | }
92 | task javadoc(type: Javadoc) {
93 | source = android.sourceSets.main.java.srcDirs
94 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
95 | classpath += configurations.compile
96 | failOnError false
97 | }
98 | task javadocJar(type: Jar, dependsOn: javadoc) {
99 | classifier = 'javadoc'
100 | from javadoc.destinationDir
101 | }
102 | artifacts {
103 | archives javadocJar
104 | archives sourcesJar
105 | }
106 | if (file('local.properties').exists()) {
107 | Properties properties = new Properties()
108 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
109 | bintray {
110 | user = properties.getProperty("bintray.user")
111 | key = properties.getProperty("bintray.apikey")
112 | configurations = ['archives']
113 | pkg {
114 | repo = "maven" // The repo we upload to
115 | name = "AndroidSoundTouch" //Project name
116 | websiteUrl = siteUrl
117 | vcsUrl = gitUrl
118 | licenses = ["LGPL-3.0"]
119 | publish = true
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/soundtouch/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/soundtouch/src/androidTest/java/io/github/junyuecao/soundtouch/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package io.github.junyuecao.soundtouch;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("io.github.junyuecao.soundtouchjava.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/soundtouch/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/Android.mk:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2010 The Android Open Source Project
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 | # $Id: Android.mk 216 2015-05-18 15:28:41Z oparviai $
16 |
17 | LOCAL_PATH := $(call my-dir)
18 |
19 | include $(CLEAR_VARS)
20 |
21 | # *** Remember: Change -O0 into -O2 in add-applications.mk ***
22 | LOCAL_MODULE := native-lib
23 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/SoundTouch/include
24 | LOCAL_SRC_FILES := SoundTouchJNI.cpp SoundTouch/AAFilter.cpp SoundTouch/FIFOSampleBuffer.cpp \
25 | SoundTouch/FIRFilter.cpp SoundTouch/cpu_detect_x86.cpp \
26 | SoundTouch/sse_optimized.cpp \
27 | SoundTouch/RateTransposer.cpp SoundTouch/SoundTouch.cpp \
28 | SoundTouch/InterpolateCubic.cpp SoundTouch/InterpolateLinear.cpp \
29 | SoundTouch/InterpolateShannon.cpp SoundTouch/TDStretch.cpp \
30 | SoundTouch/BPMDetect.cpp SoundTouch/PeakFinder.cpp
31 |
32 | # for native audio
33 | # LOCAL_SHARED_LIBRARIES += -lgcc
34 | # --whole-archive -lgcc
35 | # for logging
36 | LOCAL_LDLIBS += -llog
37 | # for native asset manager
38 | #LOCAL_LDLIBS += -landroid
39 |
40 | # Custom Flags:
41 | # -fvisibility=hidden : don't export all symbols
42 | LOCAL_CFLAGS += -fvisibility=hidden -fdata-sections -ffunction-sections
43 |
44 | # OpenMP mode : enable these flags to enable using OpenMP for parallel computation
45 | #LOCAL_CFLAGS += -fopenmp
46 | #LOCAL_LDFLAGS += -fopenmp
47 |
48 |
49 | # Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs
50 | LOCAL_ARM_MODE := arm
51 |
52 | include $(BUILD_SHARED_LIBRARY)
53 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/Application.mk:
--------------------------------------------------------------------------------
1 | # $Id: Application.mk 212 2015-05-15 10:22:36Z oparviai $
2 | #
3 | # Build library bilaries for all supported architectures
4 | #
5 |
6 | APP_ABI := all #armeabi-v7a armeabi
7 | APP_OPTIM := release
8 | APP_STL := stlport_static
9 | APP_CPPFLAGS := -fexceptions -D SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS
10 |
11 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/AAFilter.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// FIR low-pass (anti-alias) filter with filter coefficient design routine and
4 | /// MMX optimization.
5 | ///
6 | /// Anti-alias filter is used to prevent folding of high frequencies when
7 | /// transposing the sample rate with interpolation.
8 | ///
9 | /// Author : Copyright (c) Olli Parviainen
10 | /// Author e-mail : oparviai 'at' iki.fi
11 | /// SoundTouch WWW: http://www.surina.net/soundtouch
12 | ///
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // Last changed : $Date: 2016-01-12 19:26:21 +0200 (ti, 12 tammi 2016) $
16 | // File revision : $Revision: 4 $
17 | //
18 | // $Id: AAFilter.cpp 240 2016-01-12 17:26:21Z oparviai $
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////
21 | //
22 | // License :
23 | //
24 | // SoundTouch audio processing library
25 | // Copyright (c) Olli Parviainen
26 | //
27 | // This library is free software; you can redistribute it and/or
28 | // modify it under the terms of the GNU Lesser General Public
29 | // License as published by the Free Software Foundation; either
30 | // version 2.1 of the License, or (at your option) any later version.
31 | //
32 | // This library is distributed in the hope that it will be useful,
33 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 | // Lesser General Public License for more details.
36 | //
37 | // You should have received a copy of the GNU Lesser General Public
38 | // License along with this library; if not, write to the Free Software
39 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 |
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include "AAFilter.h"
48 | #include "FIRFilter.h"
49 |
50 | using namespace soundtouch;
51 |
52 | #define PI 3.14159265358979323846
53 | #define TWOPI (2 * PI)
54 |
55 | // define this to save AA filter coefficients to a file
56 | // #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
57 |
58 | #ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
59 | #include
60 |
61 | static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
62 | {
63 | FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
64 | if (fptr == NULL) return;
65 |
66 | for (int i = 0; i < len; i ++)
67 | {
68 | double temp = coeffs[i];
69 | fprintf(fptr, "%lf\n", temp);
70 | }
71 | fclose(fptr);
72 | }
73 |
74 | #else
75 | #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
76 | #endif
77 |
78 |
79 | /*****************************************************************************
80 | *
81 | * Implementation of the class 'AAFilter'
82 | *
83 | *****************************************************************************/
84 |
85 | AAFilter::AAFilter(uint len)
86 | {
87 | pFIR = FIRFilter::newInstance();
88 | cutoffFreq = 0.5;
89 | setLength(len);
90 | }
91 |
92 |
93 |
94 | AAFilter::~AAFilter()
95 | {
96 | delete pFIR;
97 | }
98 |
99 |
100 |
101 | // Sets new anti-alias filter cut-off edge frequency, scaled to
102 | // sampling frequency (nyquist frequency = 0.5).
103 | // The filter will cut frequencies higher than the given frequency.
104 | void AAFilter::setCutoffFreq(double newCutoffFreq)
105 | {
106 | cutoffFreq = newCutoffFreq;
107 | calculateCoeffs();
108 | }
109 |
110 |
111 |
112 | // Sets number of FIR filter taps
113 | void AAFilter::setLength(uint newLength)
114 | {
115 | length = newLength;
116 | calculateCoeffs();
117 | }
118 |
119 |
120 |
121 | // Calculates coefficients for a low-pass FIR filter using Hamming window
122 | void AAFilter::calculateCoeffs()
123 | {
124 | uint i;
125 | double cntTemp, temp, tempCoeff,h, w;
126 | double wc;
127 | double scaleCoeff, sum;
128 | double *work;
129 | SAMPLETYPE *coeffs;
130 |
131 | assert(length >= 2);
132 | assert(length % 4 == 0);
133 | assert(cutoffFreq >= 0);
134 | assert(cutoffFreq <= 0.5);
135 |
136 | work = new double[length];
137 | coeffs = new SAMPLETYPE[length];
138 |
139 | wc = 2.0 * PI * cutoffFreq;
140 | tempCoeff = TWOPI / (double)length;
141 |
142 | sum = 0;
143 | for (i = 0; i < length; i ++)
144 | {
145 | cntTemp = (double)i - (double)(length / 2);
146 |
147 | temp = cntTemp * wc;
148 | if (temp != 0)
149 | {
150 | h = sin(temp) / temp; // sinc function
151 | }
152 | else
153 | {
154 | h = 1.0;
155 | }
156 | w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
157 |
158 | temp = w * h;
159 | work[i] = temp;
160 |
161 | // calc net sum of coefficients
162 | sum += temp;
163 | }
164 |
165 | // ensure the sum of coefficients is larger than zero
166 | assert(sum > 0);
167 |
168 | // ensure we've really designed a lowpass filter...
169 | assert(work[length/2] > 0);
170 | assert(work[length/2 + 1] > -1e-6);
171 | assert(work[length/2 - 1] > -1e-6);
172 |
173 | // Calculate a scaling coefficient in such a way that the result can be
174 | // divided by 16384
175 | scaleCoeff = 16384.0f / sum;
176 |
177 | for (i = 0; i < length; i ++)
178 | {
179 | temp = work[i] * scaleCoeff;
180 | //#if SOUNDTOUCH_INTEGER_SAMPLES
181 | // scale & round to nearest integer
182 | temp += (temp >= 0) ? 0.5 : -0.5;
183 | // ensure no overfloods
184 | assert(temp >= -32768 && temp <= 32767);
185 | //#endif
186 | coeffs[i] = (SAMPLETYPE)temp;
187 | }
188 |
189 | // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
190 | pFIR->setCoefficients(coeffs, length, 14);
191 |
192 | _DEBUG_SAVE_AAFIR_COEFFS(coeffs, length);
193 |
194 | delete[] work;
195 | delete[] coeffs;
196 | }
197 |
198 |
199 | // Applies the filter to the given sequence of samples.
200 | // Note : The amount of outputted samples is by value of 'filter length'
201 | // smaller than the amount of input samples.
202 | uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
203 | {
204 | return pFIR->evaluate(dest, src, numSamples, numChannels);
205 | }
206 |
207 |
208 | /// Applies the filter to the given src & dest pipes, so that processed amount of
209 | /// samples get removed from src, and produced amount added to dest
210 | /// Note : The amount of outputted samples is by value of 'filter length'
211 | /// smaller than the amount of input samples.
212 | uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
213 | {
214 | SAMPLETYPE *pdest;
215 | const SAMPLETYPE *psrc;
216 | uint numSrcSamples;
217 | uint result;
218 | int numChannels = src.getChannels();
219 |
220 | assert(numChannels == dest.getChannels());
221 |
222 | numSrcSamples = src.numSamples();
223 | psrc = src.ptrBegin();
224 | pdest = dest.ptrEnd(numSrcSamples);
225 | result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
226 | src.receiveSamples(result);
227 | dest.putSamples(result);
228 |
229 | return result;
230 | }
231 |
232 |
233 | uint AAFilter::getLength() const
234 | {
235 | return pFIR->getLength();
236 | }
237 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/AAFilter.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
4 | /// while maintaining the original pitch by using a time domain WSOLA-like method
5 | /// with several performance-increasing tweaks.
6 | ///
7 | /// Anti-alias filter is used to prevent folding of high frequencies when
8 | /// transposing the sample rate with interpolation.
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // Last changed : $Date: 2014-01-07 21:41:23 +0200 (ti, 07 tammi 2014) $
17 | // File revision : $Revision: 4 $
18 | //
19 | // $Id: AAFilter.h 187 2014-01-07 19:41:23Z oparviai $
20 | //
21 | ////////////////////////////////////////////////////////////////////////////////
22 | //
23 | // License :
24 | //
25 | // SoundTouch audio processing library
26 | // Copyright (c) Olli Parviainen
27 | //
28 | // This library is free software; you can redistribute it and/or
29 | // modify it under the terms of the GNU Lesser General Public
30 | // License as published by the Free Software Foundation; either
31 | // version 2.1 of the License, or (at your option) any later version.
32 | //
33 | // This library is distributed in the hope that it will be useful,
34 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
35 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 | // Lesser General Public License for more details.
37 | //
38 | // You should have received a copy of the GNU Lesser General Public
39 | // License along with this library; if not, write to the Free Software
40 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 | //
42 | ////////////////////////////////////////////////////////////////////////////////
43 |
44 | #ifndef AAFilter_H
45 | #define AAFilter_H
46 |
47 | #include "STTypes.h"
48 | #include "FIFOSampleBuffer.h"
49 |
50 | namespace soundtouch
51 | {
52 |
53 | class AAFilter
54 | {
55 | protected:
56 | class FIRFilter *pFIR;
57 |
58 | /// Low-pass filter cut-off frequency, negative = invalid
59 | double cutoffFreq;
60 |
61 | /// num of filter taps
62 | uint length;
63 |
64 | /// Calculate the FIR coefficients realizing the given cutoff-frequency
65 | void calculateCoeffs();
66 | public:
67 | AAFilter(uint length);
68 |
69 | ~AAFilter();
70 |
71 | /// Sets new anti-alias filter cut-off edge frequency, scaled to sampling
72 | /// frequency (nyquist frequency = 0.5). The filter will cut off the
73 | /// frequencies than that.
74 | void setCutoffFreq(double newCutoffFreq);
75 |
76 | /// Sets number of FIR filter taps, i.e. ~filter complexity
77 | void setLength(uint newLength);
78 |
79 | uint getLength() const;
80 |
81 | /// Applies the filter to the given sequence of samples.
82 | /// Note : The amount of outputted samples is by value of 'filter length'
83 | /// smaller than the amount of input samples.
84 | uint evaluate(SAMPLETYPE *dest,
85 | const SAMPLETYPE *src,
86 | uint numSamples,
87 | uint numChannels) const;
88 |
89 | /// Applies the filter to the given src & dest pipes, so that processed amount of
90 | /// samples get removed from src, and produced amount added to dest
91 | /// Note : The amount of outputted samples is by value of 'filter length'
92 | /// smaller than the amount of input samples.
93 | uint evaluate(FIFOSampleBuffer &dest,
94 | FIFOSampleBuffer &src) const;
95 |
96 | };
97 |
98 | }
99 |
100 | #endif
101 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/BPMDetect.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Beats-per-minute (BPM) detection routine.
4 | ///
5 | /// The beat detection algorithm works as follows:
6 | /// - Use function 'inputSamples' to input a chunks of samples to the class for
7 | /// analysis. It's a good idea to enter a large sound file or stream in smallish
8 | /// chunks of around few kilosamples in order not to extinguish too much RAM memory.
9 | /// - Inputted sound data is decimated to approx 500 Hz to reduce calculation burden,
10 | /// which is basically ok as low (bass) frequencies mostly determine the beat rate.
11 | /// Simple averaging is used for anti-alias filtering because the resulting signal
12 | /// quality isn't of that high importance.
13 | /// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
14 | /// taking absolute value that's smoothed by sliding average. Signal levels that
15 | /// are below a couple of times the general RMS amplitude level are cut away to
16 | /// leave only notable peaks there.
17 | /// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
18 | /// autocorrelation function of the enveloped signal.
19 | /// - After whole sound data file has been analyzed as above, the bpm level is
20 | /// detected by function 'getBpm' that finds the highest peak of the autocorrelation
21 | /// function, calculates it's precise location and converts this reading to bpm's.
22 | ///
23 | /// Author : Copyright (c) Olli Parviainen
24 | /// Author e-mail : oparviai 'at' iki.fi
25 | /// SoundTouch WWW: http://www.surina.net/soundtouch
26 | ///
27 | ////////////////////////////////////////////////////////////////////////////////
28 | //
29 | // Last changed : $Date: 2016-01-05 22:59:57 +0200 (ti, 05 tammi 2016) $
30 | // File revision : $Revision: 4 $
31 | //
32 | // $Id: BPMDetect.cpp 237 2016-01-05 20:59:57Z oparviai $
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 | //
36 | // License :
37 | //
38 | // SoundTouch audio processing library
39 | // Copyright (c) Olli Parviainen
40 | //
41 | // This library is free software; you can redistribute it and/or
42 | // modify it under the terms of the GNU Lesser General Public
43 | // License as published by the Free Software Foundation; either
44 | // version 2.1 of the License, or (at your option) any later version.
45 | //
46 | // This library is distributed in the hope that it will be useful,
47 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
48 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
49 | // Lesser General Public License for more details.
50 | //
51 | // You should have received a copy of the GNU Lesser General Public
52 | // License along with this library; if not, write to the Free Software
53 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 | //
55 | ////////////////////////////////////////////////////////////////////////////////
56 |
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include "FIFOSampleBuffer.h"
62 | #include "PeakFinder.h"
63 | #include "BPMDetect.h"
64 |
65 | using namespace soundtouch;
66 |
67 | #define INPUT_BLOCK_SAMPLES 2048
68 | #define DECIMATED_BLOCK_SAMPLES 256
69 |
70 | /// Target sample rate after decimation
71 | const int target_srate = 1000;
72 |
73 | /// XCorr update sequence size, update in about 200msec chunks
74 | const int xcorr_update_sequence = 200;
75 |
76 | /// XCorr decay time constant, decay to half in 30 seconds
77 | /// If it's desired to have the system adapt quicker to beat rate
78 | /// changes within a continuing music stream, then the
79 | /// 'xcorr_decay_time_constant' value can be reduced, yet that
80 | /// can increase possibility of glitches in bpm detection.
81 | const double xcorr_decay_time_constant = 30.0;
82 |
83 | ////////////////////////////////////////////////////////////////////////////////
84 |
85 | // Enable following define to create bpm analysis file:
86 |
87 | // #define _CREATE_BPM_DEBUG_FILE
88 |
89 | #ifdef _CREATE_BPM_DEBUG_FILE
90 |
91 | #define DEBUGFILE_NAME "c:\\temp\\soundtouch-bpm-debug.txt"
92 |
93 | static void _SaveDebugData(const float *data, int minpos, int maxpos, double coeff)
94 | {
95 | FILE *fptr = fopen(DEBUGFILE_NAME, "wt");
96 | int i;
97 |
98 | if (fptr)
99 | {
100 | printf("\n\nWriting BPM debug data into file " DEBUGFILE_NAME "\n\n");
101 | for (i = minpos; i < maxpos; i ++)
102 | {
103 | fprintf(fptr, "%d\t%.1lf\t%f\n", i, coeff / (double)i, data[i]);
104 | }
105 | fclose(fptr);
106 | }
107 | }
108 | #else
109 | #define _SaveDebugData(a,b,c,d)
110 | #endif
111 |
112 | ////////////////////////////////////////////////////////////////////////////////
113 |
114 |
115 | BPMDetect::BPMDetect(int numChannels, int aSampleRate)
116 | {
117 | this->sampleRate = aSampleRate;
118 | this->channels = numChannels;
119 |
120 | decimateSum = 0;
121 | decimateCount = 0;
122 |
123 | // choose decimation factor so that result is approx. 1000 Hz
124 | decimateBy = sampleRate / target_srate;
125 | assert(decimateBy > 0);
126 | assert(INPUT_BLOCK_SAMPLES < decimateBy * DECIMATED_BLOCK_SAMPLES);
127 |
128 | // Calculate window length & starting item according to desired min & max bpms
129 | windowLen = (60 * sampleRate) / (decimateBy * MIN_BPM);
130 | windowStart = (60 * sampleRate) / (decimateBy * MAX_BPM);
131 |
132 | assert(windowLen > windowStart);
133 |
134 | // allocate new working objects
135 | xcorr = new float[windowLen];
136 | memset(xcorr, 0, windowLen * sizeof(float));
137 |
138 | // allocate processing buffer
139 | buffer = new FIFOSampleBuffer();
140 | // we do processing in mono mode
141 | buffer->setChannels(1);
142 | buffer->clear();
143 | }
144 |
145 |
146 |
147 | BPMDetect::~BPMDetect()
148 | {
149 | delete[] xcorr;
150 | delete buffer;
151 | }
152 |
153 |
154 |
155 | /// convert to mono, low-pass filter & decimate to about 500 Hz.
156 | /// return number of outputted samples.
157 | ///
158 | /// Decimation is used to remove the unnecessary frequencies and thus to reduce
159 | /// the amount of data needed to be processed as calculating autocorrelation
160 | /// function is a very-very heavy operation.
161 | ///
162 | /// Anti-alias filtering is done simply by averaging the samples. This is really a
163 | /// poor-man's anti-alias filtering, but it's not so critical in this kind of application
164 | /// (it'd also be difficult to design a high-quality filter with steep cut-off at very
165 | /// narrow band)
166 | int BPMDetect::decimate(SAMPLETYPE *dest, const SAMPLETYPE *src, int numsamples)
167 | {
168 | int count, outcount;
169 | LONG_SAMPLETYPE out;
170 |
171 | assert(channels > 0);
172 | assert(decimateBy > 0);
173 | outcount = 0;
174 | for (count = 0; count < numsamples; count ++)
175 | {
176 | int j;
177 |
178 | // convert to mono and accumulate
179 | for (j = 0; j < channels; j ++)
180 | {
181 | decimateSum += src[j];
182 | }
183 | src += j;
184 |
185 | decimateCount ++;
186 | if (decimateCount >= decimateBy)
187 | {
188 | // Store every Nth sample only
189 | out = (LONG_SAMPLETYPE)(decimateSum / (decimateBy * channels));
190 | decimateSum = 0;
191 | decimateCount = 0;
192 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
193 | // check ranges for sure (shouldn't actually be necessary)
194 | if (out > 32767)
195 | {
196 | out = 32767;
197 | }
198 | else if (out < -32768)
199 | {
200 | out = -32768;
201 | }
202 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
203 | dest[outcount] = (SAMPLETYPE)out;
204 | outcount ++;
205 | }
206 | }
207 | return outcount;
208 | }
209 |
210 |
211 |
212 | // Calculates autocorrelation function of the sample history buffer
213 | void BPMDetect::updateXCorr(int process_samples)
214 | {
215 | int offs;
216 | SAMPLETYPE *pBuffer;
217 |
218 | assert(buffer->numSamples() >= (uint)(process_samples + windowLen));
219 |
220 | pBuffer = buffer->ptrBegin();
221 |
222 | // calculate decay factor for xcorr filtering
223 | float xcorr_decay = (float)pow(0.5, 1.0 / (xcorr_decay_time_constant * target_srate / process_samples));
224 |
225 | #pragma omp parallel for
226 | for (offs = windowStart; offs < windowLen; offs ++)
227 | {
228 | LONG_SAMPLETYPE sum;
229 | int i;
230 |
231 | sum = 0;
232 | for (i = 0; i < process_samples; i ++)
233 | {
234 | sum += pBuffer[i] * pBuffer[i + offs]; // scaling the sub-result shouldn't be necessary
235 | }
236 | xcorr[offs] *= xcorr_decay; // decay 'xcorr' here with suitable time constant.
237 |
238 | xcorr[offs] += fabs((float)sum);
239 | }
240 | }
241 |
242 |
243 |
244 | void BPMDetect::inputSamples(const SAMPLETYPE *samples, int numSamples)
245 | {
246 | SAMPLETYPE decimated[DECIMATED_BLOCK_SAMPLES];
247 |
248 | // iterate so that max INPUT_BLOCK_SAMPLES processed per iteration
249 | while (numSamples > 0)
250 | {
251 | int block;
252 | int decSamples;
253 |
254 | block = (numSamples > INPUT_BLOCK_SAMPLES) ? INPUT_BLOCK_SAMPLES : numSamples;
255 |
256 | // decimate. note that converts to mono at the same time
257 | decSamples = decimate(decimated, samples, block);
258 | samples += block * channels;
259 | numSamples -= block;
260 |
261 | buffer->putSamples(decimated, decSamples);
262 | }
263 |
264 | // when the buffer has enought samples for processing...
265 | while ((int)buffer->numSamples() >= windowLen + xcorr_update_sequence)
266 | {
267 | // ... calculate autocorrelations for oldest samples...
268 | updateXCorr(xcorr_update_sequence);
269 | // ... and remove these from the buffer
270 | buffer->receiveSamples(xcorr_update_sequence);
271 | }
272 | }
273 |
274 |
275 |
276 | void BPMDetect::removeBias()
277 | {
278 | int i;
279 | float minval = 1e12f; // arbitrary large number
280 |
281 | for (i = windowStart; i < windowLen; i ++)
282 | {
283 | if (xcorr[i] < minval)
284 | {
285 | minval = xcorr[i];
286 | }
287 | }
288 |
289 | for (i = windowStart; i < windowLen; i ++)
290 | {
291 | xcorr[i] -= minval;
292 | }
293 | }
294 |
295 |
296 | float BPMDetect::getBpm()
297 | {
298 | double peakPos;
299 | double coeff;
300 | PeakFinder peakFinder;
301 |
302 | coeff = 60.0 * ((double)sampleRate / (double)decimateBy);
303 |
304 | // save bpm debug analysis data if debug data enabled
305 | _SaveDebugData(xcorr, windowStart, windowLen, coeff);
306 |
307 | // remove bias from xcorr data
308 | removeBias();
309 |
310 | // find peak position
311 | peakPos = peakFinder.detectPeak(xcorr, windowStart, windowLen);
312 |
313 | assert(decimateBy != 0);
314 | if (peakPos < 1e-9) return 0.0; // detection failed.
315 |
316 | // calculate BPM
317 | return (float) (coeff / peakPos);
318 | }
319 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/FIFOSampleBuffer.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// A buffer class for temporarily storaging sound samples, operates as a
4 | /// first-in-first-out pipe.
5 | ///
6 | /// Samples are added to the end of the sample buffer with the 'putSamples'
7 | /// function, and are received from the beginning of the buffer by calling
8 | /// the 'receiveSamples' function. The class automatically removes the
9 | /// outputted samples from the buffer, as well as grows the buffer size
10 | /// whenever necessary.
11 | ///
12 | /// Author : Copyright (c) Olli Parviainen
13 | /// Author e-mail : oparviai 'at' iki.fi
14 | /// SoundTouch WWW: http://www.surina.net/soundtouch
15 | ///
16 | ////////////////////////////////////////////////////////////////////////////////
17 | //
18 | // Last changed : $Date: 2012-11-08 20:53:01 +0200 (to, 08 marras 2012) $
19 | // File revision : $Revision: 4 $
20 | //
21 | // $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 | //
25 | // License :
26 | //
27 | // SoundTouch audio processing library
28 | // Copyright (c) Olli Parviainen
29 | //
30 | // This library is free software; you can redistribute it and/or
31 | // modify it under the terms of the GNU Lesser General Public
32 | // License as published by the Free Software Foundation; either
33 | // version 2.1 of the License, or (at your option) any later version.
34 | //
35 | // This library is distributed in the hope that it will be useful,
36 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | // Lesser General Public License for more details.
39 | //
40 | // You should have received a copy of the GNU Lesser General Public
41 | // License along with this library; if not, write to the Free Software
42 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43 | //
44 | ////////////////////////////////////////////////////////////////////////////////
45 |
46 | #include
47 | #include
48 | #include
49 | #include
50 |
51 | #include "FIFOSampleBuffer.h"
52 |
53 | using namespace soundtouch;
54 |
55 | // Constructor
56 | FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
57 | {
58 | assert(numChannels > 0);
59 | sizeInBytes = 0; // reasonable initial value
60 | buffer = NULL;
61 | bufferUnaligned = NULL;
62 | samplesInBuffer = 0;
63 | bufferPos = 0;
64 | channels = (uint)numChannels;
65 | ensureCapacity(32); // allocate initial capacity
66 | }
67 |
68 |
69 | // destructor
70 | FIFOSampleBuffer::~FIFOSampleBuffer()
71 | {
72 | delete[] bufferUnaligned;
73 | bufferUnaligned = NULL;
74 | buffer = NULL;
75 | }
76 |
77 |
78 | // Sets number of channels, 1 = mono, 2 = stereo
79 | void FIFOSampleBuffer::setChannels(int numChannels)
80 | {
81 | uint usedBytes;
82 |
83 | assert(numChannels > 0);
84 | usedBytes = channels * samplesInBuffer;
85 | channels = (uint)numChannels;
86 | samplesInBuffer = usedBytes / channels;
87 | }
88 |
89 |
90 | // if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
91 | // zeroes this pointer by copying samples from the 'bufferPos' pointer
92 | // location on to the beginning of the buffer.
93 | void FIFOSampleBuffer::rewind()
94 | {
95 | if (buffer && bufferPos)
96 | {
97 | memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
98 | bufferPos = 0;
99 | }
100 | }
101 |
102 |
103 | // Adds 'numSamples' pcs of samples from the 'samples' memory position to
104 | // the sample buffer.
105 | void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
106 | {
107 | memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
108 | samplesInBuffer += nSamples;
109 | }
110 |
111 |
112 | // Increases the number of samples in the buffer without copying any actual
113 | // samples.
114 | //
115 | // This function is used to update the number of samples in the sample buffer
116 | // when accessing the buffer directly with 'ptrEnd' function. Please be
117 | // careful though!
118 | void FIFOSampleBuffer::putSamples(uint nSamples)
119 | {
120 | uint req;
121 |
122 | req = samplesInBuffer + nSamples;
123 | ensureCapacity(req);
124 | samplesInBuffer += nSamples;
125 | }
126 |
127 |
128 | // Returns a pointer to the end of the used part of the sample buffer (i.e.
129 | // where the new samples are to be inserted). This function may be used for
130 | // inserting new samples into the sample buffer directly. Please be careful!
131 | //
132 | // Parameter 'slackCapacity' tells the function how much free capacity (in
133 | // terms of samples) there _at least_ should be, in order to the caller to
134 | // succesfully insert all the required samples to the buffer. When necessary,
135 | // the function grows the buffer size to comply with this requirement.
136 | //
137 | // When using this function as means for inserting new samples, also remember
138 | // to increase the sample count afterwards, by calling the
139 | // 'putSamples(numSamples)' function.
140 | SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
141 | {
142 | ensureCapacity(samplesInBuffer + slackCapacity);
143 | return buffer + samplesInBuffer * channels;
144 | }
145 |
146 |
147 | // Returns a pointer to the beginning of the currently non-outputted samples.
148 | // This function is provided for accessing the output samples directly.
149 | // Please be careful!
150 | //
151 | // When using this function to output samples, also remember to 'remove' the
152 | // outputted samples from the buffer by calling the
153 | // 'receiveSamples(numSamples)' function
154 | SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
155 | {
156 | assert(buffer);
157 | return buffer + bufferPos * channels;
158 | }
159 |
160 |
161 | // Ensures that the buffer has enought capacity, i.e. space for _at least_
162 | // 'capacityRequirement' number of samples. The buffer is grown in steps of
163 | // 4 kilobytes to eliminate the need for frequently growing up the buffer,
164 | // as well as to round the buffer size up to the virtual memory page size.
165 | void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
166 | {
167 | SAMPLETYPE *tempUnaligned, *temp;
168 |
169 | if (capacityRequirement > getCapacity())
170 | {
171 | // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
172 | sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
173 | assert(sizeInBytes % 2 == 0);
174 | tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
175 | if (tempUnaligned == NULL)
176 | {
177 | ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
178 | }
179 | // Align the buffer to begin at 16byte cache line boundary for optimal performance
180 | temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned);
181 | if (samplesInBuffer)
182 | {
183 | memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
184 | }
185 | delete[] bufferUnaligned;
186 | buffer = temp;
187 | bufferUnaligned = tempUnaligned;
188 | bufferPos = 0;
189 | }
190 | else
191 | {
192 | // simply rewind the buffer (if necessary)
193 | rewind();
194 | }
195 | }
196 |
197 |
198 | // Returns the current buffer capacity in terms of samples
199 | uint FIFOSampleBuffer::getCapacity() const
200 | {
201 | return sizeInBytes / (channels * sizeof(SAMPLETYPE));
202 | }
203 |
204 |
205 | // Returns the number of samples currently in the buffer
206 | uint FIFOSampleBuffer::numSamples() const
207 | {
208 | return samplesInBuffer;
209 | }
210 |
211 |
212 | // Output samples from beginning of the sample buffer. Copies demanded number
213 | // of samples to output and removes them from the sample buffer. If there
214 | // are less than 'numsample' samples in the buffer, returns all available.
215 | //
216 | // Returns number of samples copied.
217 | uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
218 | {
219 | uint num;
220 |
221 | num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
222 |
223 | memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
224 | return receiveSamples(num);
225 | }
226 |
227 |
228 | // Removes samples from the beginning of the sample buffer without copying them
229 | // anywhere. Used to reduce the number of samples in the buffer, when accessing
230 | // the sample buffer with the 'ptrBegin' function.
231 | uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
232 | {
233 | if (maxSamples >= samplesInBuffer)
234 | {
235 | uint temp;
236 |
237 | temp = samplesInBuffer;
238 | samplesInBuffer = 0;
239 | return temp;
240 | }
241 |
242 | samplesInBuffer -= maxSamples;
243 | bufferPos += maxSamples;
244 |
245 | return maxSamples;
246 | }
247 |
248 |
249 | // Returns nonzero if the sample buffer is empty
250 | int FIFOSampleBuffer::isEmpty() const
251 | {
252 | return (samplesInBuffer == 0) ? 1 : 0;
253 | }
254 |
255 |
256 | // Clears the sample buffer
257 | void FIFOSampleBuffer::clear()
258 | {
259 | samplesInBuffer = 0;
260 | bufferPos = 0;
261 | }
262 |
263 |
264 | /// allow trimming (downwards) amount of samples in pipeline.
265 | /// Returns adjusted amount of samples
266 | uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
267 | {
268 | if (numSamples < samplesInBuffer)
269 | {
270 | samplesInBuffer = numSamples;
271 | }
272 | return samplesInBuffer;
273 | }
274 |
275 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/FIRFilter.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// General FIR digital filter routines with MMX optimization.
4 | ///
5 | /// Notes : MMX optimized functions reside in a separate, platform-specific file,
6 | /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
7 | ///
8 | /// This source file contains OpenMP optimizations that allow speeding up the
9 | /// corss-correlation algorithm by executing it in several threads / CPU cores
10 | /// in parallel. See the following article link for more detailed discussion
11 | /// about SoundTouch OpenMP optimizations:
12 | /// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices
13 | ///
14 | /// Author : Copyright (c) Olli Parviainen
15 | /// Author e-mail : oparviai 'at' iki.fi
16 | /// SoundTouch WWW: http://www.surina.net/soundtouch
17 | ///
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // Last changed : $Date: 2015-11-05 19:46:08 +0200 (to, 05 marras 2015) $
21 | // File revision : $Revision: 4 $
22 | //
23 | // $Id: FIRFilter.cpp 234 2015-11-05 17:46:08Z oparviai $
24 | //
25 | ////////////////////////////////////////////////////////////////////////////////
26 | //
27 | // License :
28 | //
29 | // SoundTouch audio processing library
30 | // Copyright (c) Olli Parviainen
31 | //
32 | // This library is free software; you can redistribute it and/or
33 | // modify it under the terms of the GNU Lesser General Public
34 | // License as published by the Free Software Foundation; either
35 | // version 2.1 of the License, or (at your option) any later version.
36 | //
37 | // This library is distributed in the hope that it will be useful,
38 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
39 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 | // Lesser General Public License for more details.
41 | //
42 | // You should have received a copy of the GNU Lesser General Public
43 | // License along with this library; if not, write to the Free Software
44 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 | //
46 | ////////////////////////////////////////////////////////////////////////////////
47 |
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include "FIRFilter.h"
53 | #include "cpu_detect.h"
54 |
55 | using namespace soundtouch;
56 |
57 | /*****************************************************************************
58 | *
59 | * Implementation of the class 'FIRFilter'
60 | *
61 | *****************************************************************************/
62 |
63 | FIRFilter::FIRFilter()
64 | {
65 | resultDivFactor = 0;
66 | resultDivider = 0;
67 | length = 0;
68 | lengthDiv8 = 0;
69 | filterCoeffs = NULL;
70 | }
71 |
72 |
73 | FIRFilter::~FIRFilter()
74 | {
75 | delete[] filterCoeffs;
76 | }
77 |
78 | // Usual C-version of the filter routine for stereo sound
79 | uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
80 | {
81 | int j, end;
82 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
83 | // when using floating point samples, use a scaler instead of a divider
84 | // because division is much slower operation than multiplying.
85 | double dScaler = 1.0 / (double)resultDivider;
86 | #endif
87 |
88 | assert(length != 0);
89 | assert(src != NULL);
90 | assert(dest != NULL);
91 | assert(filterCoeffs != NULL);
92 |
93 | end = 2 * (numSamples - length);
94 |
95 | #pragma omp parallel for
96 | for (j = 0; j < end; j += 2)
97 | {
98 | const SAMPLETYPE *ptr;
99 | LONG_SAMPLETYPE suml, sumr;
100 | uint i;
101 |
102 | suml = sumr = 0;
103 | ptr = src + j;
104 |
105 | for (i = 0; i < length; i += 4)
106 | {
107 | // loop is unrolled by factor of 4 here for efficiency
108 | suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
109 | ptr[2 * i + 2] * filterCoeffs[i + 1] +
110 | ptr[2 * i + 4] * filterCoeffs[i + 2] +
111 | ptr[2 * i + 6] * filterCoeffs[i + 3];
112 | sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
113 | ptr[2 * i + 3] * filterCoeffs[i + 1] +
114 | ptr[2 * i + 5] * filterCoeffs[i + 2] +
115 | ptr[2 * i + 7] * filterCoeffs[i + 3];
116 | }
117 |
118 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
119 | suml >>= resultDivFactor;
120 | sumr >>= resultDivFactor;
121 | // saturate to 16 bit integer limits
122 | suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
123 | // saturate to 16 bit integer limits
124 | sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
125 | #else
126 | suml *= dScaler;
127 | sumr *= dScaler;
128 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
129 | dest[j] = (SAMPLETYPE)suml;
130 | dest[j + 1] = (SAMPLETYPE)sumr;
131 | }
132 | return numSamples - length;
133 | }
134 |
135 |
136 |
137 |
138 | // Usual C-version of the filter routine for mono sound
139 | uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
140 | {
141 | int j, end;
142 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
143 | // when using floating point samples, use a scaler instead of a divider
144 | // because division is much slower operation than multiplying.
145 | double dScaler = 1.0 / (double)resultDivider;
146 | #endif
147 |
148 | assert(length != 0);
149 |
150 | end = numSamples - length;
151 | #pragma omp parallel for
152 | for (j = 0; j < end; j ++)
153 | {
154 | const SAMPLETYPE *pSrc = src + j;
155 | LONG_SAMPLETYPE sum;
156 | uint i;
157 |
158 | sum = 0;
159 | for (i = 0; i < length; i += 4)
160 | {
161 | // loop is unrolled by factor of 4 here for efficiency
162 | sum += pSrc[i + 0] * filterCoeffs[i + 0] +
163 | pSrc[i + 1] * filterCoeffs[i + 1] +
164 | pSrc[i + 2] * filterCoeffs[i + 2] +
165 | pSrc[i + 3] * filterCoeffs[i + 3];
166 | }
167 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
168 | sum >>= resultDivFactor;
169 | // saturate to 16 bit integer limits
170 | sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
171 | #else
172 | sum *= dScaler;
173 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
174 | dest[j] = (SAMPLETYPE)sum;
175 | }
176 | return end;
177 | }
178 |
179 |
180 | uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels)
181 | {
182 | int j, end;
183 |
184 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
185 | // when using floating point samples, use a scaler instead of a divider
186 | // because division is much slower operation than multiplying.
187 | double dScaler = 1.0 / (double)resultDivider;
188 | #endif
189 |
190 | assert(length != 0);
191 | assert(src != NULL);
192 | assert(dest != NULL);
193 | assert(filterCoeffs != NULL);
194 | assert(numChannels < 16);
195 |
196 | end = numChannels * (numSamples - length);
197 |
198 | #pragma omp parallel for
199 | for (j = 0; j < end; j += numChannels)
200 | {
201 | const SAMPLETYPE *ptr;
202 | LONG_SAMPLETYPE sums[16];
203 | uint c, i;
204 |
205 | for (c = 0; c < numChannels; c ++)
206 | {
207 | sums[c] = 0;
208 | }
209 |
210 | ptr = src + j;
211 |
212 | for (i = 0; i < length; i ++)
213 | {
214 | SAMPLETYPE coef=filterCoeffs[i];
215 | for (c = 0; c < numChannels; c ++)
216 | {
217 | sums[c] += ptr[0] * coef;
218 | ptr ++;
219 | }
220 | }
221 |
222 | for (c = 0; c < numChannels; c ++)
223 | {
224 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
225 | sums[c] >>= resultDivFactor;
226 | #else
227 | sums[c] *= dScaler;
228 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
229 | dest[j+c] = (SAMPLETYPE)sums[c];
230 | }
231 | }
232 | return numSamples - length;
233 | }
234 |
235 |
236 | // Set filter coeffiecients and length.
237 | //
238 | // Throws an exception if filter length isn't divisible by 8
239 | void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
240 | {
241 | assert(newLength > 0);
242 | if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
243 |
244 | lengthDiv8 = newLength / 8;
245 | length = lengthDiv8 * 8;
246 | assert(length == newLength);
247 |
248 | resultDivFactor = uResultDivFactor;
249 | resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
250 |
251 | delete[] filterCoeffs;
252 | filterCoeffs = new SAMPLETYPE[length];
253 | memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
254 | }
255 |
256 |
257 | uint FIRFilter::getLength() const
258 | {
259 | return length;
260 | }
261 |
262 |
263 |
264 | // Applies the filter to the given sequence of samples.
265 | //
266 | // Note : The amount of outputted samples is by value of 'filter_length'
267 | // smaller than the amount of input samples.
268 | uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels)
269 | {
270 | assert(length > 0);
271 | assert(lengthDiv8 * 8 == length);
272 |
273 | if (numSamples < length) return 0;
274 |
275 | #ifndef USE_MULTICH_ALWAYS
276 | if (numChannels == 1)
277 | {
278 | return evaluateFilterMono(dest, src, numSamples);
279 | }
280 | else if (numChannels == 2)
281 | {
282 | return evaluateFilterStereo(dest, src, numSamples);
283 | }
284 | else
285 | #endif // USE_MULTICH_ALWAYS
286 | {
287 | assert(numChannels > 0);
288 | return evaluateFilterMulti(dest, src, numSamples, numChannels);
289 | }
290 | }
291 |
292 |
293 |
294 | // Operator 'new' is overloaded so that it automatically creates a suitable instance
295 | // depending on if we've a MMX-capable CPU available or not.
296 | void * FIRFilter::operator new(size_t s)
297 | {
298 | // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
299 | ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
300 | return newInstance();
301 | }
302 |
303 |
304 | FIRFilter * FIRFilter::newInstance()
305 | {
306 | uint uExtensions;
307 |
308 | uExtensions = detectCPUextensions();
309 |
310 | // Check if MMX/SSE instruction set extensions supported by CPU
311 |
312 | #ifdef SOUNDTOUCH_ALLOW_MMX
313 | // MMX routines available only with integer sample types
314 | if (uExtensions & SUPPORT_MMX)
315 | {
316 | return ::new FIRFilterMMX;
317 | }
318 | else
319 | #endif // SOUNDTOUCH_ALLOW_MMX
320 |
321 | #ifdef SOUNDTOUCH_ALLOW_SSE
322 | if (uExtensions & SUPPORT_SSE)
323 | {
324 | // SSE support
325 | return ::new FIRFilterSSE;
326 | }
327 | else
328 | #endif // SOUNDTOUCH_ALLOW_SSE
329 |
330 | {
331 | // ISA optimizations not supported, use plain C version
332 | return ::new FIRFilter;
333 | }
334 | }
335 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/FIRFilter.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// General FIR digital filter routines with MMX optimization.
4 | ///
5 | /// Note : MMX optimized functions reside in a separate, platform-specific file,
6 | /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
7 | ///
8 | /// Author : Copyright (c) Olli Parviainen
9 | /// Author e-mail : oparviai 'at' iki.fi
10 | /// SoundTouch WWW: http://www.surina.net/soundtouch
11 | ///
12 | ////////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Last changed : $Date: 2015-02-21 23:24:29 +0200 (la, 21 helmi 2015) $
15 | // File revision : $Revision: 4 $
16 | //
17 | // $Id: FIRFilter.h 202 2015-02-21 21:24:29Z oparviai $
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | //
21 | // License :
22 | //
23 | // SoundTouch audio processing library
24 | // Copyright (c) Olli Parviainen
25 | //
26 | // This library is free software; you can redistribute it and/or
27 | // modify it under the terms of the GNU Lesser General Public
28 | // License as published by the Free Software Foundation; either
29 | // version 2.1 of the License, or (at your option) any later version.
30 | //
31 | // This library is distributed in the hope that it will be useful,
32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | // Lesser General Public License for more details.
35 | //
36 | // You should have received a copy of the GNU Lesser General Public
37 | // License along with this library; if not, write to the Free Software
38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 |
42 | #ifndef FIRFilter_H
43 | #define FIRFilter_H
44 |
45 | #include
46 | #include "STTypes.h"
47 |
48 | namespace soundtouch
49 | {
50 |
51 | class FIRFilter
52 | {
53 | protected:
54 | // Number of FIR filter taps
55 | uint length;
56 | // Number of FIR filter taps divided by 8
57 | uint lengthDiv8;
58 |
59 | // Result divider factor in 2^k format
60 | uint resultDivFactor;
61 |
62 | // Result divider value.
63 | SAMPLETYPE resultDivider;
64 |
65 | // Memory for filter coefficients
66 | SAMPLETYPE *filterCoeffs;
67 |
68 | virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
69 | const SAMPLETYPE *src,
70 | uint numSamples) const;
71 | virtual uint evaluateFilterMono(SAMPLETYPE *dest,
72 | const SAMPLETYPE *src,
73 | uint numSamples) const;
74 | virtual uint evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels);
75 |
76 | public:
77 | FIRFilter();
78 | virtual ~FIRFilter();
79 |
80 | /// Operator 'new' is overloaded so that it automatically creates a suitable instance
81 | /// depending on if we've a MMX-capable CPU available or not.
82 | static void * operator new(size_t s);
83 |
84 | static FIRFilter *newInstance();
85 |
86 | /// Applies the filter to the given sequence of samples.
87 | /// Note : The amount of outputted samples is by value of 'filter_length'
88 | /// smaller than the amount of input samples.
89 | ///
90 | /// \return Number of samples copied to 'dest'.
91 | uint evaluate(SAMPLETYPE *dest,
92 | const SAMPLETYPE *src,
93 | uint numSamples,
94 | uint numChannels);
95 |
96 | uint getLength() const;
97 |
98 | virtual void setCoefficients(const SAMPLETYPE *coeffs,
99 | uint newLength,
100 | uint uResultDivFactor);
101 | };
102 |
103 |
104 | // Optional subclasses that implement CPU-specific optimizations:
105 |
106 | #ifdef SOUNDTOUCH_ALLOW_MMX
107 |
108 | /// Class that implements MMX optimized functions exclusive for 16bit integer samples type.
109 | class FIRFilterMMX : public FIRFilter
110 | {
111 | protected:
112 | short *filterCoeffsUnalign;
113 | short *filterCoeffsAlign;
114 |
115 | virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const;
116 | public:
117 | FIRFilterMMX();
118 | ~FIRFilterMMX();
119 |
120 | virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
121 | };
122 |
123 | #endif // SOUNDTOUCH_ALLOW_MMX
124 |
125 |
126 | #ifdef SOUNDTOUCH_ALLOW_SSE
127 | /// Class that implements SSE optimized functions exclusive for floating point samples type.
128 | class FIRFilterSSE : public FIRFilter
129 | {
130 | protected:
131 | float *filterCoeffsUnalign;
132 | float *filterCoeffsAlign;
133 |
134 | virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
135 | public:
136 | FIRFilterSSE();
137 | ~FIRFilterSSE();
138 |
139 | virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
140 | };
141 |
142 | #endif // SOUNDTOUCH_ALLOW_SSE
143 |
144 | }
145 |
146 | #endif // FIRFilter_H
147 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/InterpolateCubic.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Cubic interpolation routine.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateCubic.cpp 179 2014-01-06 18:41:42Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #include
37 | #include
38 | #include "InterpolateCubic.h"
39 | #include "STTypes.h"
40 |
41 | using namespace soundtouch;
42 |
43 | // cubic interpolation coefficients
44 | static const float _coeffs[]=
45 | { -0.5f, 1.0f, -0.5f, 0.0f,
46 | 1.5f, -2.5f, 0.0f, 1.0f,
47 | -1.5f, 2.0f, 0.5f, 0.0f,
48 | 0.5f, -0.5f, 0.0f, 0.0f};
49 |
50 |
51 | InterpolateCubic::InterpolateCubic()
52 | {
53 | fract = 0;
54 | }
55 |
56 |
57 | void InterpolateCubic::resetRegisters()
58 | {
59 | fract = 0;
60 | }
61 |
62 |
63 | /// Transpose mono audio. Returns number of produced output samples, and
64 | /// updates "srcSamples" to amount of consumed source samples
65 | int InterpolateCubic::transposeMono(SAMPLETYPE *pdest,
66 | const SAMPLETYPE *psrc,
67 | int &srcSamples)
68 | {
69 | int i;
70 | int srcSampleEnd = srcSamples - 4;
71 | int srcCount = 0;
72 |
73 | i = 0;
74 | while (srcCount < srcSampleEnd)
75 | {
76 | float out;
77 | const float x3 = 1.0f;
78 | const float x2 = (float)fract; // x
79 | const float x1 = x2*x2; // x^2
80 | const float x0 = x1*x2; // x^3
81 | float y0, y1, y2, y3;
82 |
83 | assert(fract < 1.0);
84 |
85 | y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
86 | y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
87 | y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
88 | y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
89 |
90 | out = y0 * psrc[0] + y1 * psrc[1] + y2 * psrc[2] + y3 * psrc[3];
91 |
92 | pdest[i] = (SAMPLETYPE)out;
93 | i ++;
94 |
95 | // update position fraction
96 | fract += rate;
97 | // update whole positions
98 | int whole = (int)fract;
99 | fract -= whole;
100 | psrc += whole;
101 | srcCount += whole;
102 | }
103 | srcSamples = srcCount;
104 | return i;
105 | }
106 |
107 |
108 | /// Transpose stereo audio. Returns number of produced output samples, and
109 | /// updates "srcSamples" to amount of consumed source samples
110 | int InterpolateCubic::transposeStereo(SAMPLETYPE *pdest,
111 | const SAMPLETYPE *psrc,
112 | int &srcSamples)
113 | {
114 | int i;
115 | int srcSampleEnd = srcSamples - 4;
116 | int srcCount = 0;
117 |
118 | i = 0;
119 | while (srcCount < srcSampleEnd)
120 | {
121 | const float x3 = 1.0f;
122 | const float x2 = (float)fract; // x
123 | const float x1 = x2*x2; // x^2
124 | const float x0 = x1*x2; // x^3
125 | float y0, y1, y2, y3;
126 | float out0, out1;
127 |
128 | assert(fract < 1.0);
129 |
130 | y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
131 | y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
132 | y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
133 | y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
134 |
135 | out0 = y0 * psrc[0] + y1 * psrc[2] + y2 * psrc[4] + y3 * psrc[6];
136 | out1 = y0 * psrc[1] + y1 * psrc[3] + y2 * psrc[5] + y3 * psrc[7];
137 |
138 | pdest[2*i] = (SAMPLETYPE)out0;
139 | pdest[2*i+1] = (SAMPLETYPE)out1;
140 | i ++;
141 |
142 | // update position fraction
143 | fract += rate;
144 | // update whole positions
145 | int whole = (int)fract;
146 | fract -= whole;
147 | psrc += 2*whole;
148 | srcCount += whole;
149 | }
150 | srcSamples = srcCount;
151 | return i;
152 | }
153 |
154 |
155 | /// Transpose multi-channel audio. Returns number of produced output samples, and
156 | /// updates "srcSamples" to amount of consumed source samples
157 | int InterpolateCubic::transposeMulti(SAMPLETYPE *pdest,
158 | const SAMPLETYPE *psrc,
159 | int &srcSamples)
160 | {
161 | int i;
162 | int srcSampleEnd = srcSamples - 4;
163 | int srcCount = 0;
164 |
165 | i = 0;
166 | while (srcCount < srcSampleEnd)
167 | {
168 | const float x3 = 1.0f;
169 | const float x2 = (float)fract; // x
170 | const float x1 = x2*x2; // x^2
171 | const float x0 = x1*x2; // x^3
172 | float y0, y1, y2, y3;
173 |
174 | assert(fract < 1.0);
175 |
176 | y0 = _coeffs[0] * x0 + _coeffs[1] * x1 + _coeffs[2] * x2 + _coeffs[3] * x3;
177 | y1 = _coeffs[4] * x0 + _coeffs[5] * x1 + _coeffs[6] * x2 + _coeffs[7] * x3;
178 | y2 = _coeffs[8] * x0 + _coeffs[9] * x1 + _coeffs[10] * x2 + _coeffs[11] * x3;
179 | y3 = _coeffs[12] * x0 + _coeffs[13] * x1 + _coeffs[14] * x2 + _coeffs[15] * x3;
180 |
181 | for (int c = 0; c < numChannels; c ++)
182 | {
183 | float out;
184 | out = y0 * psrc[c] + y1 * psrc[c + numChannels] + y2 * psrc[c + 2 * numChannels] + y3 * psrc[c + 3 * numChannels];
185 | pdest[0] = (SAMPLETYPE)out;
186 | pdest ++;
187 | }
188 | i ++;
189 |
190 | // update position fraction
191 | fract += rate;
192 | // update whole positions
193 | int whole = (int)fract;
194 | fract -= whole;
195 | psrc += numChannels*whole;
196 | srcCount += whole;
197 | }
198 | srcSamples = srcCount;
199 | return i;
200 | }
201 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/InterpolateCubic.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Cubic interpolation routine.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateCubic.h 225 2015-07-26 14:45:48Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #ifndef _InterpolateCubic_H_
37 | #define _InterpolateCubic_H_
38 |
39 | #include "RateTransposer.h"
40 | #include "STTypes.h"
41 |
42 | namespace soundtouch
43 | {
44 |
45 | class InterpolateCubic : public TransposerBase
46 | {
47 | protected:
48 | virtual void resetRegisters();
49 | virtual int transposeMono(SAMPLETYPE *dest,
50 | const SAMPLETYPE *src,
51 | int &srcSamples);
52 | virtual int transposeStereo(SAMPLETYPE *dest,
53 | const SAMPLETYPE *src,
54 | int &srcSamples);
55 | virtual int transposeMulti(SAMPLETYPE *dest,
56 | const SAMPLETYPE *src,
57 | int &srcSamples);
58 |
59 | double fract;
60 |
61 | public:
62 | InterpolateCubic();
63 | };
64 |
65 | }
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/InterpolateLinear.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Linear interpolation algorithm.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateLinear.cpp 225 2015-07-26 14:45:48Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #include
37 | #include
38 | #include "InterpolateLinear.h"
39 |
40 | using namespace soundtouch;
41 |
42 | //////////////////////////////////////////////////////////////////////////////
43 | //
44 | // InterpolateLinearInteger - integer arithmetic implementation
45 | //
46 |
47 | /// fixed-point interpolation routine precision
48 | #define SCALE 65536
49 |
50 |
51 | // Constructor
52 | InterpolateLinearInteger::InterpolateLinearInteger() : TransposerBase()
53 | {
54 | // Notice: use local function calling syntax for sake of clarity,
55 | // to indicate the fact that C++ constructor can't call virtual functions.
56 | resetRegisters();
57 | setRate(1.0f);
58 | }
59 |
60 |
61 | void InterpolateLinearInteger::resetRegisters()
62 | {
63 | iFract = 0;
64 | }
65 |
66 |
67 | // Transposes the sample rate of the given samples using linear interpolation.
68 | // 'Mono' version of the routine. Returns the number of samples returned in
69 | // the "dest" buffer
70 | int InterpolateLinearInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
71 | {
72 | int i;
73 | int srcSampleEnd = srcSamples - 1;
74 | int srcCount = 0;
75 |
76 | i = 0;
77 | while (srcCount < srcSampleEnd)
78 | {
79 | LONG_SAMPLETYPE temp;
80 |
81 | assert(iFract < SCALE);
82 |
83 | temp = (SCALE - iFract) * src[0] + iFract * src[1];
84 | dest[i] = (SAMPLETYPE)(temp / SCALE);
85 | i++;
86 |
87 | iFract += iRate;
88 |
89 | int iWhole = iFract / SCALE;
90 | iFract -= iWhole * SCALE;
91 | srcCount += iWhole;
92 | src += iWhole;
93 | }
94 | srcSamples = srcCount;
95 |
96 | return i;
97 | }
98 |
99 |
100 | // Transposes the sample rate of the given samples using linear interpolation.
101 | // 'Stereo' version of the routine. Returns the number of samples returned in
102 | // the "dest" buffer
103 | int InterpolateLinearInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
104 | {
105 | int i;
106 | int srcSampleEnd = srcSamples - 1;
107 | int srcCount = 0;
108 |
109 | i = 0;
110 | while (srcCount < srcSampleEnd)
111 | {
112 | LONG_SAMPLETYPE temp0;
113 | LONG_SAMPLETYPE temp1;
114 |
115 | assert(iFract < SCALE);
116 |
117 | temp0 = (SCALE - iFract) * src[0] + iFract * src[2];
118 | temp1 = (SCALE - iFract) * src[1] + iFract * src[3];
119 | dest[0] = (SAMPLETYPE)(temp0 / SCALE);
120 | dest[1] = (SAMPLETYPE)(temp1 / SCALE);
121 | dest += 2;
122 | i++;
123 |
124 | iFract += iRate;
125 |
126 | int iWhole = iFract / SCALE;
127 | iFract -= iWhole * SCALE;
128 | srcCount += iWhole;
129 | src += 2*iWhole;
130 | }
131 | srcSamples = srcCount;
132 |
133 | return i;
134 | }
135 |
136 |
137 | int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
138 | {
139 | int i;
140 | int srcSampleEnd = srcSamples - 1;
141 | int srcCount = 0;
142 |
143 | i = 0;
144 | while (srcCount < srcSampleEnd)
145 | {
146 | LONG_SAMPLETYPE temp, vol1;
147 |
148 | assert(iFract < SCALE);
149 | vol1 = (SCALE - iFract);
150 | for (int c = 0; c < numChannels; c ++)
151 | {
152 | temp = vol1 * src[c] + iFract * src[c + numChannels];
153 | dest[0] = (SAMPLETYPE)(temp / SCALE);
154 | dest ++;
155 | }
156 | i++;
157 |
158 | iFract += iRate;
159 |
160 | int iWhole = iFract / SCALE;
161 | iFract -= iWhole * SCALE;
162 | srcCount += iWhole;
163 | src += iWhole * numChannels;
164 | }
165 | srcSamples = srcCount;
166 |
167 | return i;
168 | }
169 |
170 |
171 | // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
172 | // iRate, larger faster iRates.
173 | void InterpolateLinearInteger::setRate(double newRate)
174 | {
175 | iRate = (int)(newRate * SCALE + 0.5);
176 | TransposerBase::setRate(newRate);
177 | }
178 |
179 |
180 | //////////////////////////////////////////////////////////////////////////////
181 | //
182 | // InterpolateLinearFloat - floating point arithmetic implementation
183 | //
184 | //////////////////////////////////////////////////////////////////////////////
185 |
186 |
187 | // Constructor
188 | InterpolateLinearFloat::InterpolateLinearFloat() : TransposerBase()
189 | {
190 | // Notice: use local function calling syntax for sake of clarity,
191 | // to indicate the fact that C++ constructor can't call virtual functions.
192 | resetRegisters();
193 | setRate(1.0);
194 | }
195 |
196 |
197 | void InterpolateLinearFloat::resetRegisters()
198 | {
199 | fract = 0;
200 | }
201 |
202 |
203 | // Transposes the sample rate of the given samples using linear interpolation.
204 | // 'Mono' version of the routine. Returns the number of samples returned in
205 | // the "dest" buffer
206 | int InterpolateLinearFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
207 | {
208 | int i;
209 | int srcSampleEnd = srcSamples - 1;
210 | int srcCount = 0;
211 |
212 | i = 0;
213 | while (srcCount < srcSampleEnd)
214 | {
215 | double out;
216 | assert(fract < 1.0);
217 |
218 | out = (1.0 - fract) * src[0] + fract * src[1];
219 | dest[i] = (SAMPLETYPE)out;
220 | i ++;
221 |
222 | // update position fraction
223 | fract += rate;
224 | // update whole positions
225 | int whole = (int)fract;
226 | fract -= whole;
227 | src += whole;
228 | srcCount += whole;
229 | }
230 | srcSamples = srcCount;
231 | return i;
232 | }
233 |
234 |
235 | // Transposes the sample rate of the given samples using linear interpolation.
236 | // 'Mono' version of the routine. Returns the number of samples returned in
237 | // the "dest" buffer
238 | int InterpolateLinearFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
239 | {
240 | int i;
241 | int srcSampleEnd = srcSamples - 1;
242 | int srcCount = 0;
243 |
244 | i = 0;
245 | while (srcCount < srcSampleEnd)
246 | {
247 | double out0, out1;
248 | assert(fract < 1.0);
249 |
250 | out0 = (1.0 - fract) * src[0] + fract * src[2];
251 | out1 = (1.0 - fract) * src[1] + fract * src[3];
252 | dest[2*i] = (SAMPLETYPE)out0;
253 | dest[2*i+1] = (SAMPLETYPE)out1;
254 | i ++;
255 |
256 | // update position fraction
257 | fract += rate;
258 | // update whole positions
259 | int whole = (int)fract;
260 | fract -= whole;
261 | src += 2*whole;
262 | srcCount += whole;
263 | }
264 | srcSamples = srcCount;
265 | return i;
266 | }
267 |
268 |
269 | int InterpolateLinearFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples)
270 | {
271 | int i;
272 | int srcSampleEnd = srcSamples - 1;
273 | int srcCount = 0;
274 |
275 | i = 0;
276 | while (srcCount < srcSampleEnd)
277 | {
278 | float temp, vol1, fract_float;
279 |
280 | vol1 = (float)(1.0 - fract);
281 | fract_float = (float)fract;
282 | for (int c = 0; c < numChannels; c ++)
283 | {
284 | temp = vol1 * src[c] + fract_float * src[c + numChannels];
285 | *dest = (SAMPLETYPE)temp;
286 | dest ++;
287 | }
288 | i++;
289 |
290 | fract += rate;
291 |
292 | int iWhole = (int)fract;
293 | fract -= iWhole;
294 | srcCount += iWhole;
295 | src += iWhole * numChannels;
296 | }
297 | srcSamples = srcCount;
298 |
299 | return i;
300 | }
301 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/InterpolateLinear.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Linear interpolation routine.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // $Id: InterpolateLinear.h 225 2015-07-26 14:45:48Z oparviai $
12 | //
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // License :
16 | //
17 | // SoundTouch audio processing library
18 | // Copyright (c) Olli Parviainen
19 | //
20 | // This library is free software; you can redistribute it and/or
21 | // modify it under the terms of the GNU Lesser General Public
22 | // License as published by the Free Software Foundation; either
23 | // version 2.1 of the License, or (at your option) any later version.
24 | //
25 | // This library is distributed in the hope that it will be useful,
26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 | // Lesser General Public License for more details.
29 | //
30 | // You should have received a copy of the GNU Lesser General Public
31 | // License along with this library; if not, write to the Free Software
32 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 |
36 | #ifndef _InterpolateLinear_H_
37 | #define _InterpolateLinear_H_
38 |
39 | #include "RateTransposer.h"
40 | #include "STTypes.h"
41 |
42 | namespace soundtouch
43 | {
44 |
45 | /// Linear transposer class that uses integer arithmetics
46 | class InterpolateLinearInteger : public TransposerBase
47 | {
48 | protected:
49 | int iFract;
50 | int iRate;
51 |
52 | virtual void resetRegisters();
53 |
54 | virtual int transposeMono(SAMPLETYPE *dest,
55 | const SAMPLETYPE *src,
56 | int &srcSamples);
57 | virtual int transposeStereo(SAMPLETYPE *dest,
58 | const SAMPLETYPE *src,
59 | int &srcSamples);
60 | virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
61 | public:
62 | InterpolateLinearInteger();
63 |
64 | /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
65 | /// rate, larger faster rates.
66 | virtual void setRate(double newRate);
67 | };
68 |
69 |
70 | /// Linear transposer class that uses floating point arithmetics
71 | class InterpolateLinearFloat : public TransposerBase
72 | {
73 | protected:
74 | double fract;
75 |
76 | virtual void resetRegisters();
77 |
78 | virtual int transposeMono(SAMPLETYPE *dest,
79 | const SAMPLETYPE *src,
80 | int &srcSamples);
81 | virtual int transposeStereo(SAMPLETYPE *dest,
82 | const SAMPLETYPE *src,
83 | int &srcSamples);
84 | virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
85 |
86 | public:
87 | InterpolateLinearFloat();
88 | };
89 |
90 | }
91 |
92 | #endif
93 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/InterpolateShannon.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample interpolation routine using 8-tap band-limited Shannon interpolation
4 | /// with kaiser window.
5 | ///
6 | /// Notice. This algorithm is remarkably much heavier than linear or cubic
7 | /// interpolation, and not remarkably better than cubic algorithm. Thus mostly
8 | /// for experimental purposes
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // $Id: InterpolateShannon.cpp 195 2014-04-06 15:57:21Z oparviai $
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // License :
21 | //
22 | // SoundTouch audio processing library
23 | // Copyright (c) Olli Parviainen
24 | //
25 | // This library is free software; you can redistribute it and/or
26 | // modify it under the terms of the GNU Lesser General Public
27 | // License as published by the Free Software Foundation; either
28 | // version 2.1 of the License, or (at your option) any later version.
29 | //
30 | // This library is distributed in the hope that it will be useful,
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 | // Lesser General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public
36 | // License along with this library; if not, write to the Free Software
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 |
41 | #include
42 | #include "InterpolateShannon.h"
43 | #include "STTypes.h"
44 |
45 | using namespace soundtouch;
46 |
47 |
48 | /// Kaiser window with beta = 2.0
49 | /// Values scaled down by 5% to avoid overflows
50 | static const double _kaiser8[8] =
51 | {
52 | 0.41778693317814,
53 | 0.64888025049173,
54 | 0.83508562409944,
55 | 0.93887857733412,
56 | 0.93887857733412,
57 | 0.83508562409944,
58 | 0.64888025049173,
59 | 0.41778693317814
60 | };
61 |
62 |
63 | InterpolateShannon::InterpolateShannon()
64 | {
65 | fract = 0;
66 | }
67 |
68 |
69 | void InterpolateShannon::resetRegisters()
70 | {
71 | fract = 0;
72 | }
73 |
74 |
75 | #define PI 3.1415926536
76 | #define sinc(x) (sin(PI * (x)) / (PI * (x)))
77 |
78 | /// Transpose mono audio. Returns number of produced output samples, and
79 | /// updates "srcSamples" to amount of consumed source samples
80 | int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,
81 | const SAMPLETYPE *psrc,
82 | int &srcSamples)
83 | {
84 | int i;
85 | int srcSampleEnd = srcSamples - 8;
86 | int srcCount = 0;
87 |
88 | i = 0;
89 | while (srcCount < srcSampleEnd)
90 | {
91 | double out;
92 | assert(fract < 1.0);
93 |
94 | out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0];
95 | out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1];
96 | out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2];
97 | if (fract < 1e-6)
98 | {
99 | out += psrc[3] * _kaiser8[3]; // sinc(0) = 1
100 | }
101 | else
102 | {
103 | out += psrc[3] * sinc(- fract) * _kaiser8[3];
104 | }
105 | out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4];
106 | out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5];
107 | out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6];
108 | out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7];
109 |
110 | pdest[i] = (SAMPLETYPE)out;
111 | i ++;
112 |
113 | // update position fraction
114 | fract += rate;
115 | // update whole positions
116 | int whole = (int)fract;
117 | fract -= whole;
118 | psrc += whole;
119 | srcCount += whole;
120 | }
121 | srcSamples = srcCount;
122 | return i;
123 | }
124 |
125 |
126 | /// Transpose stereo audio. Returns number of produced output samples, and
127 | /// updates "srcSamples" to amount of consumed source samples
128 | int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
129 | const SAMPLETYPE *psrc,
130 | int &srcSamples)
131 | {
132 | int i;
133 | int srcSampleEnd = srcSamples - 8;
134 | int srcCount = 0;
135 |
136 | i = 0;
137 | while (srcCount < srcSampleEnd)
138 | {
139 | double out0, out1, w;
140 | assert(fract < 1.0);
141 |
142 | w = sinc(-3.0 - fract) * _kaiser8[0];
143 | out0 = psrc[0] * w; out1 = psrc[1] * w;
144 | w = sinc(-2.0 - fract) * _kaiser8[1];
145 | out0 += psrc[2] * w; out1 += psrc[3] * w;
146 | w = sinc(-1.0 - fract) * _kaiser8[2];
147 | out0 += psrc[4] * w; out1 += psrc[5] * w;
148 | w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1
149 | out0 += psrc[6] * w; out1 += psrc[7] * w;
150 | w = sinc( 1.0 - fract) * _kaiser8[4];
151 | out0 += psrc[8] * w; out1 += psrc[9] * w;
152 | w = sinc( 2.0 - fract) * _kaiser8[5];
153 | out0 += psrc[10] * w; out1 += psrc[11] * w;
154 | w = sinc( 3.0 - fract) * _kaiser8[6];
155 | out0 += psrc[12] * w; out1 += psrc[13] * w;
156 | w = sinc( 4.0 - fract) * _kaiser8[7];
157 | out0 += psrc[14] * w; out1 += psrc[15] * w;
158 |
159 | pdest[2*i] = (SAMPLETYPE)out0;
160 | pdest[2*i+1] = (SAMPLETYPE)out1;
161 | i ++;
162 |
163 | // update position fraction
164 | fract += rate;
165 | // update whole positions
166 | int whole = (int)fract;
167 | fract -= whole;
168 | psrc += 2*whole;
169 | srcCount += whole;
170 | }
171 | srcSamples = srcCount;
172 | return i;
173 | }
174 |
175 |
176 | /// Transpose stereo audio. Returns number of produced output samples, and
177 | /// updates "srcSamples" to amount of consumed source samples
178 | int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
179 | const SAMPLETYPE *psrc,
180 | int &srcSamples)
181 | {
182 | // not implemented
183 | assert(false);
184 | return 0;
185 | }
186 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/InterpolateShannon.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample interpolation routine using 8-tap band-limited Shannon interpolation
4 | /// with kaiser window.
5 | ///
6 | /// Notice. This algorithm is remarkably much heavier than linear or cubic
7 | /// interpolation, and not remarkably better than cubic algorithm. Thus mostly
8 | /// for experimental purposes
9 | ///
10 | /// Author : Copyright (c) Olli Parviainen
11 | /// Author e-mail : oparviai 'at' iki.fi
12 | /// SoundTouch WWW: http://www.surina.net/soundtouch
13 | ///
14 | ////////////////////////////////////////////////////////////////////////////////
15 | //
16 | // $Id: InterpolateShannon.h 225 2015-07-26 14:45:48Z oparviai $
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // License :
21 | //
22 | // SoundTouch audio processing library
23 | // Copyright (c) Olli Parviainen
24 | //
25 | // This library is free software; you can redistribute it and/or
26 | // modify it under the terms of the GNU Lesser General Public
27 | // License as published by the Free Software Foundation; either
28 | // version 2.1 of the License, or (at your option) any later version.
29 | //
30 | // This library is distributed in the hope that it will be useful,
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 | // Lesser General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public
36 | // License along with this library; if not, write to the Free Software
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 |
41 | #ifndef _InterpolateShannon_H_
42 | #define _InterpolateShannon_H_
43 |
44 | #include "RateTransposer.h"
45 | #include "STTypes.h"
46 |
47 | namespace soundtouch
48 | {
49 |
50 | class InterpolateShannon : public TransposerBase
51 | {
52 | protected:
53 | void resetRegisters();
54 | int transposeMono(SAMPLETYPE *dest,
55 | const SAMPLETYPE *src,
56 | int &srcSamples);
57 | int transposeStereo(SAMPLETYPE *dest,
58 | const SAMPLETYPE *src,
59 | int &srcSamples);
60 | int transposeMulti(SAMPLETYPE *dest,
61 | const SAMPLETYPE *src,
62 | int &srcSamples);
63 |
64 | double fract;
65 |
66 | public:
67 | InterpolateShannon();
68 | };
69 |
70 | }
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/Makefile.am:
--------------------------------------------------------------------------------
1 | ## Process this file with automake to create Makefile.in
2 | ##
3 | ## $Id: Makefile.am 230 2015-09-20 07:38:32Z oparviai $
4 | ##
5 | ## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
6 | ##
7 | ## SoundTouch is free software; you can redistribute it and/or modify it under the
8 | ## terms of the GNU General Public License as published by the Free Software
9 | ## Foundation; either version 2 of the License, or (at your option) any later
10 | ## version.
11 | ##
12 | ## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY
13 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 | ## A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 | ##
16 | ## You should have received a copy of the GNU General Public License along with
17 | ## this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 | ## Place - Suite 330, Boston, MA 02111-1307, USA
19 |
20 |
21 | include $(top_srcdir)/config/am_include.mk
22 |
23 |
24 | # set to something if you want other stuff to be included in the distribution tarball
25 | EXTRA_DIST=SoundTouch.dsp SoundTouch.dsw SoundTouch.sln SoundTouch.vcproj
26 |
27 | noinst_HEADERS=AAFilter.h cpu_detect.h cpu_detect_x86.cpp FIRFilter.h RateTransposer.h TDStretch.h PeakFinder.h
28 |
29 | lib_LTLIBRARIES=libSoundTouch.la
30 | #
31 | libSoundTouch_la_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp \
32 | RateTransposer.cpp SoundTouch.cpp TDStretch.cpp cpu_detect_x86.cpp \
33 | BPMDetect.cpp PeakFinder.cpp InterpolateLinear.cpp InterpolateCubic.cpp \
34 | InterpolateShannon.cpp
35 |
36 | # Compiler flags
37 | AM_CXXFLAGS+=-O3
38 |
39 | # Compile the files that need MMX and SSE individually.
40 | libSoundTouch_la_LIBADD=libSoundTouchMMX.la libSoundTouchSSE.la
41 | noinst_LTLIBRARIES=libSoundTouchMMX.la libSoundTouchSSE.la
42 | libSoundTouchMMX_la_SOURCES=mmx_optimized.cpp
43 | libSoundTouchSSE_la_SOURCES=sse_optimized.cpp
44 |
45 | # We enable optimizations by default.
46 | # If MMX is supported compile with -mmmx.
47 | # Do not assume -msse is also supported.
48 | if HAVE_MMX
49 | libSoundTouchMMX_la_CXXFLAGS = -mmmx $(AM_CXXFLAGS)
50 | else
51 | libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS)
52 | endif
53 |
54 | # We enable optimizations by default.
55 | # If SSE is supported compile with -msse.
56 | if HAVE_SSE
57 | libSoundTouchSSE_la_CXXFLAGS = -msse $(AM_CXXFLAGS)
58 | else
59 | libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS)
60 | endif
61 |
62 | # Let the user disable optimizations if he wishes to.
63 | if !X86_OPTIMIZATIONS
64 | libSoundTouchMMX_la_CXXFLAGS = $(AM_CXXFLAGS)
65 | libSoundTouchSSE_la_CXXFLAGS = $(AM_CXXFLAGS)
66 | endif
67 |
68 | # Modify the default 0.0.0 to LIB_SONAME.0.0
69 | libSoundTouch_la_LDFLAGS=-version-info @LIB_SONAME@
70 |
71 | # other linking flags to add
72 | # noinst_LTLIBRARIES = libSoundTouchOpt.la
73 | # libSoundTouch_la_LIBADD = libSoundTouchOpt.la
74 | # libSoundTouchOpt_la_SOURCES = mmx_optimized.cpp sse_optimized.cpp
75 | # libSoundTouchOpt_la_CXXFLAGS = -O3 -msse -fcheck-new -I../../include
76 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/PeakFinder.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/junyuecao/AndroidSoundTouch/18132e55bf48204d35cd1cc57ca1f4bd7a8a764e/soundtouch/src/main/cpp/SoundTouch/PeakFinder.cpp
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/PeakFinder.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// The routine detects highest value on an array of values and calculates the
4 | /// precise peak location as a mass-center of the 'hump' around the peak value.
5 | ///
6 | /// Author : Copyright (c) Olli Parviainen
7 | /// Author e-mail : oparviai 'at' iki.fi
8 | /// SoundTouch WWW: http://www.surina.net/soundtouch
9 | ///
10 | ////////////////////////////////////////////////////////////////////////////////
11 | //
12 | // Last changed : $Date: 2011-12-30 22:33:46 +0200 (pe, 30 joulu 2011) $
13 | // File revision : $Revision: 4 $
14 | //
15 | // $Id: PeakFinder.h 132 2011-12-30 20:33:46Z oparviai $
16 | //
17 | ////////////////////////////////////////////////////////////////////////////////
18 | //
19 | // License :
20 | //
21 | // SoundTouch audio processing library
22 | // Copyright (c) Olli Parviainen
23 | //
24 | // This library is free software; you can redistribute it and/or
25 | // modify it under the terms of the GNU Lesser General Public
26 | // License as published by the Free Software Foundation; either
27 | // version 2.1 of the License, or (at your option) any later version.
28 | //
29 | // This library is distributed in the hope that it will be useful,
30 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
31 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 | // Lesser General Public License for more details.
33 | //
34 | // You should have received a copy of the GNU Lesser General Public
35 | // License along with this library; if not, write to the Free Software
36 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 | //
38 | ////////////////////////////////////////////////////////////////////////////////
39 |
40 | #ifndef _PeakFinder_H_
41 | #define _PeakFinder_H_
42 |
43 | namespace soundtouch
44 | {
45 |
46 | class PeakFinder
47 | {
48 | protected:
49 | /// Min, max allowed peak positions within the data vector
50 | int minPos, maxPos;
51 |
52 | /// Calculates the mass center between given vector items.
53 | double calcMassCenter(const float *data, ///< Data vector.
54 | int firstPos, ///< Index of first vector item beloging to the peak.
55 | int lastPos ///< Index of last vector item beloging to the peak.
56 | ) const;
57 |
58 | /// Finds the data vector index where the monotoniously decreasing signal crosses the
59 | /// given level.
60 | int findCrossingLevel(const float *data, ///< Data vector.
61 | float level, ///< Goal crossing level.
62 | int peakpos, ///< Peak position index within the data vector.
63 | int direction /// Direction where to proceed from the peak: 1 = right, -1 = left.
64 | ) const;
65 |
66 | // Finds real 'top' of a peak hump from neighnourhood of the given 'peakpos'.
67 | int findTop(const float *data, int peakpos) const;
68 |
69 |
70 | /// Finds the 'ground' level, i.e. smallest level between two neighbouring peaks, to right-
71 | /// or left-hand side of the given peak position.
72 | int findGround(const float *data, /// Data vector.
73 | int peakpos, /// Peak position index within the data vector.
74 | int direction /// Direction where to proceed from the peak: 1 = right, -1 = left.
75 | ) const;
76 |
77 | /// get exact center of peak near given position by calculating local mass of center
78 | double getPeakCenter(const float *data, int peakpos) const;
79 |
80 | public:
81 | /// Constructor.
82 | PeakFinder();
83 |
84 | /// Detect exact peak position of the data vector by finding the largest peak 'hump'
85 | /// and calculating the mass-center location of the peak hump.
86 | ///
87 | /// \return The location of the largest base harmonic peak hump.
88 | double detectPeak(const float *data, /// Data vector to be analyzed. The data vector has
89 | /// to be at least 'maxPos' items long.
90 | int minPos, ///< Min allowed peak location within the vector data.
91 | int maxPos ///< Max allowed peak location within the vector data.
92 | );
93 | };
94 |
95 | }
96 |
97 | #endif // _PeakFinder_H_
98 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/RateTransposer.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample rate transposer. Changes sample rate by using linear interpolation
4 | /// together with anti-alias filtering (first order interpolation with anti-
5 | /// alias filtering should be quite adequate for this application)
6 | ///
7 | /// Author : Copyright (c) Olli Parviainen
8 | /// Author e-mail : oparviai 'at' iki.fi
9 | /// SoundTouch WWW: http://www.surina.net/soundtouch
10 | ///
11 | ////////////////////////////////////////////////////////////////////////////////
12 | //
13 | // Last changed : $Date: 2016-10-15 22:34:59 +0300 (la, 15 loka 2016) $
14 | // File revision : $Revision: 4 $
15 | //
16 | // $Id: RateTransposer.cpp 243 2016-10-15 19:34:59Z oparviai $
17 | //
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // License :
21 | //
22 | // SoundTouch audio processing library
23 | // Copyright (c) Olli Parviainen
24 | //
25 | // This library is free software; you can redistribute it and/or
26 | // modify it under the terms of the GNU Lesser General Public
27 | // License as published by the Free Software Foundation; either
28 | // version 2.1 of the License, or (at your option) any later version.
29 | //
30 | // This library is distributed in the hope that it will be useful,
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 | // Lesser General Public License for more details.
34 | //
35 | // You should have received a copy of the GNU Lesser General Public
36 | // License along with this library; if not, write to the Free Software
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 | //
39 | ////////////////////////////////////////////////////////////////////////////////
40 |
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include "RateTransposer.h"
46 | #include "InterpolateLinear.h"
47 | #include "InterpolateCubic.h"
48 | #include "InterpolateShannon.h"
49 | #include "AAFilter.h"
50 |
51 | using namespace soundtouch;
52 |
53 | // Define default interpolation algorithm here
54 | TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
55 |
56 |
57 | // Constructor
58 | RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
59 | {
60 | bUseAAFilter = true;
61 |
62 | // Instantiates the anti-alias filter
63 | pAAFilter = new AAFilter(64);
64 | pTransposer = TransposerBase::newInstance();
65 | }
66 |
67 |
68 |
69 | RateTransposer::~RateTransposer()
70 | {
71 | delete pAAFilter;
72 | delete pTransposer;
73 | }
74 |
75 |
76 |
77 | /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
78 | void RateTransposer::enableAAFilter(bool newMode)
79 | {
80 | bUseAAFilter = newMode;
81 | }
82 |
83 |
84 | /// Returns nonzero if anti-alias filter is enabled.
85 | bool RateTransposer::isAAFilterEnabled() const
86 | {
87 | return bUseAAFilter;
88 | }
89 |
90 |
91 | AAFilter *RateTransposer::getAAFilter()
92 | {
93 | return pAAFilter;
94 | }
95 |
96 |
97 |
98 | // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
99 | // iRate, larger faster iRates.
100 | void RateTransposer::setRate(double newRate)
101 | {
102 | double fCutoff;
103 |
104 | pTransposer->setRate(newRate);
105 |
106 | // design a new anti-alias filter
107 | if (newRate > 1.0)
108 | {
109 | fCutoff = 0.5 / newRate;
110 | }
111 | else
112 | {
113 | fCutoff = 0.5 * newRate;
114 | }
115 | pAAFilter->setCutoffFreq(fCutoff);
116 | }
117 |
118 |
119 | // Adds 'nSamples' pcs of samples from the 'samples' memory position into
120 | // the input of the object.
121 | void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
122 | {
123 | processSamples(samples, nSamples);
124 | }
125 |
126 |
127 | // Transposes sample rate by applying anti-alias filter to prevent folding.
128 | // Returns amount of samples returned in the "dest" buffer.
129 | // The maximum amount of samples that can be returned at a time is set by
130 | // the 'set_returnBuffer_size' function.
131 | void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
132 | {
133 | uint count;
134 |
135 | if (nSamples == 0) return;
136 |
137 | // Store samples to input buffer
138 | inputBuffer.putSamples(src, nSamples);
139 |
140 | // If anti-alias filter is turned off, simply transpose without applying
141 | // the filter
142 | if (bUseAAFilter == false)
143 | {
144 | count = pTransposer->transpose(outputBuffer, inputBuffer);
145 | return;
146 | }
147 |
148 | assert(pAAFilter);
149 |
150 | // Transpose with anti-alias filter
151 | if (pTransposer->rate < 1.0f)
152 | {
153 | // If the parameter 'Rate' value is smaller than 1, first transpose
154 | // the samples and then apply the anti-alias filter to remove aliasing.
155 |
156 | // Transpose the samples, store the result to end of "midBuffer"
157 | pTransposer->transpose(midBuffer, inputBuffer);
158 |
159 | // Apply the anti-alias filter for transposed samples in midBuffer
160 | pAAFilter->evaluate(outputBuffer, midBuffer);
161 | }
162 | else
163 | {
164 | // If the parameter 'Rate' value is larger than 1, first apply the
165 | // anti-alias filter to remove high frequencies (prevent them from folding
166 | // over the lover frequencies), then transpose.
167 |
168 | // Apply the anti-alias filter for samples in inputBuffer
169 | pAAFilter->evaluate(midBuffer, inputBuffer);
170 |
171 | // Transpose the AA-filtered samples in "midBuffer"
172 | pTransposer->transpose(outputBuffer, midBuffer);
173 | }
174 | }
175 |
176 |
177 | // Sets the number of channels, 1 = mono, 2 = stereo
178 | void RateTransposer::setChannels(int nChannels)
179 | {
180 | assert(nChannels > 0);
181 |
182 | if (pTransposer->numChannels == nChannels) return;
183 | pTransposer->setChannels(nChannels);
184 |
185 | inputBuffer.setChannels(nChannels);
186 | midBuffer.setChannels(nChannels);
187 | outputBuffer.setChannels(nChannels);
188 | }
189 |
190 |
191 | // Clears all the samples in the object
192 | void RateTransposer::clear()
193 | {
194 | outputBuffer.clear();
195 | midBuffer.clear();
196 | inputBuffer.clear();
197 | }
198 |
199 |
200 | // Returns nonzero if there aren't any samples available for outputting.
201 | int RateTransposer::isEmpty() const
202 | {
203 | int res;
204 |
205 | res = FIFOProcessor::isEmpty();
206 | if (res == 0) return 0;
207 | return inputBuffer.isEmpty();
208 | }
209 |
210 |
211 | /// Return approximate initial input-output latency
212 | int RateTransposer::getLatency() const
213 | {
214 | return (bUseAAFilter) ? pAAFilter->getLength() : 0;
215 | }
216 |
217 |
218 | //////////////////////////////////////////////////////////////////////////////
219 | //
220 | // TransposerBase - Base class for interpolation
221 | //
222 |
223 | // static function to set interpolation algorithm
224 | void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
225 | {
226 | TransposerBase::algorithm = a;
227 | }
228 |
229 |
230 | // Transposes the sample rate of the given samples using linear interpolation.
231 | // Returns the number of samples returned in the "dest" buffer
232 | int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
233 | {
234 | int numSrcSamples = src.numSamples();
235 | int sizeDemand = (int)((double)numSrcSamples / rate) + 8;
236 | int numOutput;
237 | SAMPLETYPE *psrc = src.ptrBegin();
238 | SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
239 |
240 | #ifndef USE_MULTICH_ALWAYS
241 | if (numChannels == 1)
242 | {
243 | numOutput = transposeMono(pdest, psrc, numSrcSamples);
244 | }
245 | else if (numChannels == 2)
246 | {
247 | numOutput = transposeStereo(pdest, psrc, numSrcSamples);
248 | }
249 | else
250 | #endif // USE_MULTICH_ALWAYS
251 | {
252 | assert(numChannels > 0);
253 | numOutput = transposeMulti(pdest, psrc, numSrcSamples);
254 | }
255 | dest.putSamples(numOutput);
256 | src.receiveSamples(numSrcSamples);
257 | return numOutput;
258 | }
259 |
260 |
261 | TransposerBase::TransposerBase()
262 | {
263 | numChannels = 0;
264 | rate = 1.0f;
265 | }
266 |
267 |
268 | TransposerBase::~TransposerBase()
269 | {
270 | }
271 |
272 |
273 | void TransposerBase::setChannels(int channels)
274 | {
275 | numChannels = channels;
276 | resetRegisters();
277 | }
278 |
279 |
280 | void TransposerBase::setRate(double newRate)
281 | {
282 | rate = newRate;
283 | }
284 |
285 |
286 | // static factory function
287 | TransposerBase *TransposerBase::newInstance()
288 | {
289 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
290 | // Notice: For integer arithmetics support only linear algorithm (due to simplest calculus)
291 | return ::new InterpolateLinearInteger;
292 | #else
293 | switch (algorithm)
294 | {
295 | case LINEAR:
296 | return new InterpolateLinearFloat;
297 |
298 | case CUBIC:
299 | return new InterpolateCubic;
300 |
301 | case SHANNON:
302 | return new InterpolateShannon;
303 |
304 | default:
305 | assert(false);
306 | return NULL;
307 | }
308 | #endif
309 | }
310 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/RateTransposer.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Sample rate transposer. Changes sample rate by using linear interpolation
4 | /// together with anti-alias filtering (first order interpolation with anti-
5 | /// alias filtering should be quite adequate for this application).
6 | ///
7 | /// Use either of the derived classes of 'RateTransposerInteger' or
8 | /// 'RateTransposerFloat' for corresponding integer/floating point tranposing
9 | /// algorithm implementation.
10 | ///
11 | /// Author : Copyright (c) Olli Parviainen
12 | /// Author e-mail : oparviai 'at' iki.fi
13 | /// SoundTouch WWW: http://www.surina.net/soundtouch
14 | ///
15 | ////////////////////////////////////////////////////////////////////////////////
16 | //
17 | // Last changed : $Date: 2016-10-15 22:34:59 +0300 (la, 15 loka 2016) $
18 | // File revision : $Revision: 4 $
19 | //
20 | // $Id: RateTransposer.h 243 2016-10-15 19:34:59Z oparviai $
21 | //
22 | ////////////////////////////////////////////////////////////////////////////////
23 | //
24 | // License :
25 | //
26 | // SoundTouch audio processing library
27 | // Copyright (c) Olli Parviainen
28 | //
29 | // This library is free software; you can redistribute it and/or
30 | // modify it under the terms of the GNU Lesser General Public
31 | // License as published by the Free Software Foundation; either
32 | // version 2.1 of the License, or (at your option) any later version.
33 | //
34 | // This library is distributed in the hope that it will be useful,
35 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
36 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 | // Lesser General Public License for more details.
38 | //
39 | // You should have received a copy of the GNU Lesser General Public
40 | // License along with this library; if not, write to the Free Software
41 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 | //
43 | ////////////////////////////////////////////////////////////////////////////////
44 |
45 | #ifndef RateTransposer_H
46 | #define RateTransposer_H
47 |
48 | #include
49 | #include "AAFilter.h"
50 | #include "FIFOSamplePipe.h"
51 | #include "FIFOSampleBuffer.h"
52 |
53 | #include "STTypes.h"
54 |
55 | namespace soundtouch
56 | {
57 |
58 | /// Abstract base class for transposer implementations (linear, advanced vs integer, float etc)
59 | class TransposerBase
60 | {
61 | public:
62 | enum ALGORITHM {
63 | LINEAR = 0,
64 | CUBIC,
65 | SHANNON
66 | };
67 |
68 | protected:
69 | virtual void resetRegisters() = 0;
70 |
71 | virtual int transposeMono(SAMPLETYPE *dest,
72 | const SAMPLETYPE *src,
73 | int &srcSamples) = 0;
74 | virtual int transposeStereo(SAMPLETYPE *dest,
75 | const SAMPLETYPE *src,
76 | int &srcSamples) = 0;
77 | virtual int transposeMulti(SAMPLETYPE *dest,
78 | const SAMPLETYPE *src,
79 | int &srcSamples) = 0;
80 |
81 | static ALGORITHM algorithm;
82 |
83 | public:
84 | double rate;
85 | int numChannels;
86 |
87 | TransposerBase();
88 | virtual ~TransposerBase();
89 |
90 | virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
91 | virtual void setRate(double newRate);
92 | virtual void setChannels(int channels);
93 |
94 | // static factory function
95 | static TransposerBase *newInstance();
96 |
97 | // static function to set interpolation algorithm
98 | static void setAlgorithm(ALGORITHM a);
99 | };
100 |
101 |
102 | /// A common linear samplerate transposer class.
103 | ///
104 | class RateTransposer : public FIFOProcessor
105 | {
106 | protected:
107 | /// Anti-alias filter object
108 | AAFilter *pAAFilter;
109 | TransposerBase *pTransposer;
110 |
111 | /// Buffer for collecting samples to feed the anti-alias filter between
112 | /// two batches
113 | FIFOSampleBuffer inputBuffer;
114 |
115 | /// Buffer for keeping samples between transposing & anti-alias filter
116 | FIFOSampleBuffer midBuffer;
117 |
118 | /// Output sample buffer
119 | FIFOSampleBuffer outputBuffer;
120 |
121 | bool bUseAAFilter;
122 |
123 |
124 | /// Transposes sample rate by applying anti-alias filter to prevent folding.
125 | /// Returns amount of samples returned in the "dest" buffer.
126 | /// The maximum amount of samples that can be returned at a time is set by
127 | /// the 'set_returnBuffer_size' function.
128 | void processSamples(const SAMPLETYPE *src,
129 | uint numSamples);
130 |
131 | public:
132 | RateTransposer();
133 | virtual ~RateTransposer();
134 |
135 | /// Operator 'new' is overloaded so that it automatically creates a suitable instance
136 | /// depending on if we're to use integer or floating point arithmetics.
137 | // static void *operator new(size_t s);
138 |
139 | /// Use this function instead of "new" operator to create a new instance of this class.
140 | /// This function automatically chooses a correct implementation, depending on if
141 | /// integer ot floating point arithmetics are to be used.
142 | // static RateTransposer *newInstance();
143 |
144 | /// Returns the output buffer object
145 | FIFOSamplePipe *getOutput() { return &outputBuffer; };
146 |
147 | /// Returns the store buffer object
148 | // FIFOSamplePipe *getStore() { return &storeBuffer; };
149 |
150 | /// Return anti-alias filter object
151 | AAFilter *getAAFilter();
152 |
153 | /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
154 | void enableAAFilter(bool newMode);
155 |
156 | /// Returns nonzero if anti-alias filter is enabled.
157 | bool isAAFilterEnabled() const;
158 |
159 | /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
160 | /// rate, larger faster rates.
161 | virtual void setRate(double newRate);
162 |
163 | /// Sets the number of channels, 1 = mono, 2 = stereo
164 | void setChannels(int channels);
165 |
166 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position into
167 | /// the input of the object.
168 | void putSamples(const SAMPLETYPE *samples, uint numSamples);
169 |
170 | /// Clears all the samples in the object
171 | void clear();
172 |
173 | /// Returns nonzero if there aren't any samples available for outputting.
174 | int isEmpty() const;
175 |
176 | /// Return approximate initial input-output latency
177 | int getLatency() const;
178 | };
179 |
180 | }
181 |
182 | #endif
183 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/SoundTouch.dsp:
--------------------------------------------------------------------------------
1 | # Microsoft Developer Studio Project File - Name="SoundTouch" - Package Owner=<4>
2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00
3 | # ** DO NOT EDIT **
4 |
5 | # TARGTYPE "Win32 (x86) Static Library" 0x0104
6 |
7 | CFG=SoundTouch - Win32 Debug
8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE,
9 | !MESSAGE use the Export Makefile command and run
10 | !MESSAGE
11 | !MESSAGE NMAKE /f "SoundTouch.mak".
12 | !MESSAGE
13 | !MESSAGE You can specify a configuration when running NMAKE
14 | !MESSAGE by defining the macro CFG on the command line. For example:
15 | !MESSAGE
16 | !MESSAGE NMAKE /f "SoundTouch.mak" CFG="SoundTouch - Win32 Debug"
17 | !MESSAGE
18 | !MESSAGE Possible choices for configuration are:
19 | !MESSAGE
20 | !MESSAGE "SoundTouch - Win32 Release" (based on "Win32 (x86) Static Library")
21 | !MESSAGE "SoundTouch - Win32 Debug" (based on "Win32 (x86) Static Library")
22 | !MESSAGE
23 |
24 | # Begin Project
25 | # PROP AllowPerConfigDependencies 0
26 | # PROP Scc_ProjName ""
27 | # PROP Scc_LocalPath ""
28 | CPP=cl.exe
29 | RSC=rc.exe
30 |
31 | !IF "$(CFG)" == "SoundTouch - Win32 Release"
32 |
33 | # PROP BASE Use_MFC 0
34 | # PROP BASE Use_Debug_Libraries 0
35 | # PROP BASE Output_Dir "Release"
36 | # PROP BASE Intermediate_Dir "Release"
37 | # PROP BASE Target_Dir ""
38 | # PROP Use_MFC 0
39 | # PROP Use_Debug_Libraries 0
40 | # PROP Output_Dir "Release"
41 | # PROP Intermediate_Dir "Release"
42 | # PROP Target_Dir ""
43 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
44 | # ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
45 | # ADD BASE RSC /l 0x40b /d "NDEBUG"
46 | # ADD RSC /l 0x40b /d "NDEBUG"
47 | BSC32=bscmake.exe
48 | # ADD BASE BSC32 /nologo
49 | # ADD BSC32 /nologo
50 | LIB32=link.exe -lib
51 | # ADD BASE LIB32 /nologo
52 | # ADD LIB32 /nologo
53 | # Begin Special Build Tool
54 | SOURCE="$(InputPath)"
55 | PostBuild_Cmds=copy .\Release\SoundTouch.lib ..\..\lib\
56 | # End Special Build Tool
57 |
58 | !ELSEIF "$(CFG)" == "SoundTouch - Win32 Debug"
59 |
60 | # PROP BASE Use_MFC 0
61 | # PROP BASE Use_Debug_Libraries 1
62 | # PROP BASE Output_Dir "Debug"
63 | # PROP BASE Intermediate_Dir "Debug"
64 | # PROP BASE Target_Dir ""
65 | # PROP Use_MFC 0
66 | # PROP Use_Debug_Libraries 1
67 | # PROP Output_Dir "Debug"
68 | # PROP Intermediate_Dir "Debug"
69 | # PROP Target_Dir ""
70 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
71 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
72 | # ADD BASE RSC /l 0x40b /d "_DEBUG"
73 | # ADD RSC /l 0x40b /d "_DEBUG"
74 | BSC32=bscmake.exe
75 | # ADD BASE BSC32 /nologo
76 | # ADD BSC32 /nologo
77 | LIB32=link.exe -lib
78 | # ADD BASE LIB32 /nologo
79 | # ADD LIB32 /nologo /out:"Debug\SoundTouchD.lib"
80 | # Begin Special Build Tool
81 | SOURCE="$(InputPath)"
82 | PostBuild_Cmds=copy .\Debug\SoundTouchD.lib ..\..\lib\
83 | # End Special Build Tool
84 |
85 | !ENDIF
86 |
87 | # Begin Target
88 |
89 | # Name "SoundTouch - Win32 Release"
90 | # Name "SoundTouch - Win32 Debug"
91 | # Begin Group "Source Files"
92 |
93 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
94 | # Begin Group "bpm"
95 |
96 | # PROP Default_Filter ""
97 | # Begin Source File
98 |
99 | SOURCE=.\BPMDetect.cpp
100 | # End Source File
101 | # Begin Source File
102 |
103 | SOURCE=.\PeakFinder.cpp
104 | # End Source File
105 | # End Group
106 | # Begin Source File
107 |
108 | SOURCE=.\3dnow_win.cpp
109 | # End Source File
110 | # Begin Source File
111 |
112 | SOURCE=.\AAFilter.cpp
113 | # End Source File
114 | # Begin Source File
115 |
116 | SOURCE=.\cpu_detect_x86_win.cpp
117 | # End Source File
118 | # Begin Source File
119 |
120 | SOURCE=.\FIFOSampleBuffer.cpp
121 | # End Source File
122 | # Begin Source File
123 |
124 | SOURCE=.\FIRFilter.cpp
125 | # End Source File
126 | # Begin Source File
127 |
128 | SOURCE=.\mmx_optimized.cpp
129 | # End Source File
130 | # Begin Source File
131 |
132 | SOURCE=.\RateTransposer.cpp
133 | # End Source File
134 | # Begin Source File
135 |
136 | SOURCE=.\SoundTouch.cpp
137 | # End Source File
138 | # Begin Source File
139 |
140 | SOURCE=.\sse_optimized.cpp
141 | # End Source File
142 | # Begin Source File
143 |
144 | SOURCE=.\TDStretch.cpp
145 | # End Source File
146 | # End Group
147 | # Begin Group "Header Files"
148 |
149 | # PROP Default_Filter "h;hpp;hxx;hm;inl"
150 | # Begin Source File
151 |
152 | SOURCE=.\AAFilter.h
153 | # End Source File
154 | # Begin Source File
155 |
156 | SOURCE=.\cpu_detect.h
157 | # End Source File
158 | # Begin Source File
159 |
160 | SOURCE=..\..\include\FIFOSampleBuffer.h
161 | # End Source File
162 | # Begin Source File
163 |
164 | SOURCE=..\..\include\FIFOSamplePipe.h
165 | # End Source File
166 | # Begin Source File
167 |
168 | SOURCE=.\FIRFilter.h
169 | # End Source File
170 | # Begin Source File
171 |
172 | SOURCE=.\RateTransposer.h
173 | # End Source File
174 | # Begin Source File
175 |
176 | SOURCE=..\..\include\SoundTouch.h
177 | # End Source File
178 | # Begin Source File
179 |
180 | SOURCE=..\..\include\STTypes.h
181 | # End Source File
182 | # Begin Source File
183 |
184 | SOURCE=.\TDStretch.h
185 | # End Source File
186 | # End Group
187 | # End Target
188 | # End Project
189 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/SoundTouch.dsw:
--------------------------------------------------------------------------------
1 | Microsoft Developer Studio Workspace File, Format Version 6.00
2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
3 | #
4 | # $Id: SoundTouch.dsw 11 2008-02-10 16:26:55Z oparviai $
5 |
6 | ###############################################################################
7 |
8 | Project: "SoundTouch"=.\SoundTouch.dsp - Package Owner=<4>
9 |
10 | Package=<5>
11 | {{{
12 | }}}
13 |
14 | Package=<4>
15 | {{{
16 | }}}
17 |
18 | ###############################################################################
19 |
20 | Global:
21 |
22 | Package=<5>
23 | {{{
24 | }}}
25 |
26 | Package=<3>
27 | {{{
28 | }}}
29 |
30 | ###############################################################################
31 |
32 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/SoundTouch.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 10.00
2 | # Visual Studio 2008
3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoundTouch", "SoundTouch.vcproj", "{68A5DD20-7057-448B-8FE0-B6AC8D205509}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Win32 = Debug|Win32
8 | Debug|x64 = Debug|x64
9 | Release|Win32 = Release|Win32
10 | Release|x64 = Release|x64
11 | ReleaseX64|Win32 = ReleaseX64|Win32
12 | ReleaseX64|x64 = ReleaseX64|x64
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Debug|Win32.ActiveCfg = Debug|Win32
16 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Debug|x64.ActiveCfg = Debug|x64
17 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Release|Win32.ActiveCfg = Release|Win32
18 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.Release|x64.ActiveCfg = Release|x64
19 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|Win32.ActiveCfg = ReleaseX64|Win32
20 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|Win32.Build.0 = ReleaseX64|Win32
21 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|x64.ActiveCfg = ReleaseX64|x64
22 | {68A5DD20-7057-448B-8FE0-B6AC8D205509}.ReleaseX64|x64.Build.0 = ReleaseX64|x64
23 | EndGlobalSection
24 | GlobalSection(SolutionProperties) = preSolution
25 | HideSolutionNode = FALSE
26 | EndGlobalSection
27 | EndGlobal
28 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/cpu_detect.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// A header file for detecting the Intel MMX instructions set extension.
4 | ///
5 | /// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the
6 | /// routine implementations for x86 Windows, x86 gnu version and non-x86
7 | /// platforms, respectively.
8 | ///
9 | /// Author : Copyright (c) Olli Parviainen
10 | /// Author e-mail : oparviai 'at' iki.fi
11 | /// SoundTouch WWW: http://www.surina.net/soundtouch
12 | ///
13 | ////////////////////////////////////////////////////////////////////////////////
14 | //
15 | // Last changed : $Date: 2008-02-10 18:26:55 +0200 (su, 10 helmi 2008) $
16 | // File revision : $Revision: 4 $
17 | //
18 | // $Id: cpu_detect.h 11 2008-02-10 16:26:55Z oparviai $
19 | //
20 | ////////////////////////////////////////////////////////////////////////////////
21 | //
22 | // License :
23 | //
24 | // SoundTouch audio processing library
25 | // Copyright (c) Olli Parviainen
26 | //
27 | // This library is free software; you can redistribute it and/or
28 | // modify it under the terms of the GNU Lesser General Public
29 | // License as published by the Free Software Foundation; either
30 | // version 2.1 of the License, or (at your option) any later version.
31 | //
32 | // This library is distributed in the hope that it will be useful,
33 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 | // Lesser General Public License for more details.
36 | //
37 | // You should have received a copy of the GNU Lesser General Public
38 | // License along with this library; if not, write to the Free Software
39 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 | //
41 | ////////////////////////////////////////////////////////////////////////////////
42 |
43 | #ifndef _CPU_DETECT_H_
44 | #define _CPU_DETECT_H_
45 |
46 | #include "STTypes.h"
47 |
48 | #define SUPPORT_MMX 0x0001
49 | #define SUPPORT_3DNOW 0x0002
50 | #define SUPPORT_ALTIVEC 0x0004
51 | #define SUPPORT_SSE 0x0008
52 | #define SUPPORT_SSE2 0x0010
53 |
54 | /// Checks which instruction set extensions are supported by the CPU.
55 | ///
56 | /// \return A bitmask of supported extensions, see SUPPORT_... defines.
57 | uint detectCPUextensions(void);
58 |
59 | /// Disables given set of instruction extensions. See SUPPORT_... defines.
60 | void disableExtensions(uint wDisableMask);
61 |
62 | #endif // _CPU_DETECT_H_
63 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/cpu_detect_x86.cpp:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Generic version of the x86 CPU extension detection routine.
4 | ///
5 | /// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp'
6 | /// for the Microsoft compiler version.
7 | ///
8 | /// Author : Copyright (c) Olli Parviainen
9 | /// Author e-mail : oparviai 'at' iki.fi
10 | /// SoundTouch WWW: http://www.surina.net/soundtouch
11 | ///
12 | ////////////////////////////////////////////////////////////////////////////////
13 | //
14 | // Last changed : $Date: 2014-01-07 20:24:28 +0200 (ti, 07 tammi 2014) $
15 | // File revision : $Revision: 4 $
16 | //
17 | // $Id: cpu_detect_x86.cpp 183 2014-01-07 18:24:28Z oparviai $
18 | //
19 | ////////////////////////////////////////////////////////////////////////////////
20 | //
21 | // License :
22 | //
23 | // SoundTouch audio processing library
24 | // Copyright (c) Olli Parviainen
25 | //
26 | // This library is free software; you can redistribute it and/or
27 | // modify it under the terms of the GNU Lesser General Public
28 | // License as published by the Free Software Foundation; either
29 | // version 2.1 of the License, or (at your option) any later version.
30 | //
31 | // This library is distributed in the hope that it will be useful,
32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | // Lesser General Public License for more details.
35 | //
36 | // You should have received a copy of the GNU Lesser General Public
37 | // License along with this library; if not, write to the Free Software
38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 | //
40 | ////////////////////////////////////////////////////////////////////////////////
41 |
42 | #include "cpu_detect.h"
43 | #include "STTypes.h"
44 |
45 |
46 | #if defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
47 |
48 | #if defined(__GNUC__) && defined(__i386__)
49 | // gcc
50 | #include "cpuid.h"
51 | #elif defined(_M_IX86)
52 | // windows non-gcc
53 | #include
54 | #endif
55 |
56 | #define bit_MMX (1 << 23)
57 | #define bit_SSE (1 << 25)
58 | #define bit_SSE2 (1 << 26)
59 | #endif
60 |
61 |
62 | //////////////////////////////////////////////////////////////////////////////
63 | //
64 | // processor instructions extension detection routines
65 | //
66 | //////////////////////////////////////////////////////////////////////////////
67 |
68 | // Flag variable indicating whick ISA extensions are disabled (for debugging)
69 | static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions
70 |
71 | // Disables given set of instruction extensions. See SUPPORT_... defines.
72 | void disableExtensions(uint dwDisableMask)
73 | {
74 | _dwDisabledISA = dwDisableMask;
75 | }
76 |
77 |
78 |
79 | /// Checks which instruction set extensions are supported by the CPU.
80 | uint detectCPUextensions(void)
81 | {
82 | /// If building for a 64bit system (no Itanium) and the user wants optimizations.
83 | /// Return the OR of SUPPORT_{MMX,SSE,SSE2}. 11001 or 0x19.
84 | /// Keep the _dwDisabledISA test (2 more operations, could be eliminated).
85 | #if ((defined(__GNUC__) && defined(__x86_64__)) \
86 | || defined(_M_X64)) \
87 | && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
88 | return 0x19 & ~_dwDisabledISA;
89 |
90 | /// If building for a 32bit system and the user wants optimizations.
91 | /// Keep the _dwDisabledISA test (2 more operations, could be eliminated).
92 | #elif ((defined(__GNUC__) && defined(__i386__)) \
93 | || defined(_M_IX86)) \
94 | && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS)
95 |
96 | if (_dwDisabledISA == 0xffffffff) return 0;
97 |
98 | uint res = 0;
99 |
100 | #if defined(__GNUC__)
101 | // GCC version of cpuid. Requires GCC 4.3.0 or later for __cpuid intrinsic support.
102 | uint eax, ebx, ecx, edx; // unsigned int is the standard type. uint is defined by the compiler and not guaranteed to be portable.
103 |
104 | // Check if no cpuid support.
105 | if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) return 0; // always disable extensions.
106 |
107 | if (edx & bit_MMX) res = res | SUPPORT_MMX;
108 | if (edx & bit_SSE) res = res | SUPPORT_SSE;
109 | if (edx & bit_SSE2) res = res | SUPPORT_SSE2;
110 |
111 | #else
112 | // Window / VS version of cpuid. Notice that Visual Studio 2005 or later required
113 | // for __cpuid intrinsic support.
114 | int reg[4] = {-1};
115 |
116 | // Check if no cpuid support.
117 | __cpuid(reg,0);
118 | if ((unsigned int)reg[0] == 0) return 0; // always disable extensions.
119 |
120 | __cpuid(reg,1);
121 | if ((unsigned int)reg[3] & bit_MMX) res = res | SUPPORT_MMX;
122 | if ((unsigned int)reg[3] & bit_SSE) res = res | SUPPORT_SSE;
123 | if ((unsigned int)reg[3] & bit_SSE2) res = res | SUPPORT_SSE2;
124 |
125 | #endif
126 |
127 | return res & ~_dwDisabledISA;
128 |
129 | #else
130 |
131 | /// One of these is true:
132 | /// 1) We don't want optimizations.
133 | /// 2) Using an unsupported compiler.
134 | /// 3) Running on a non-x86 platform.
135 | return 0;
136 |
137 | #endif
138 | }
139 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/include/BPMDetect.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Beats-per-minute (BPM) detection routine.
4 | ///
5 | /// The beat detection algorithm works as follows:
6 | /// - Use function 'inputSamples' to input a chunks of samples to the class for
7 | /// analysis. It's a good idea to enter a large sound file or stream in smallish
8 | /// chunks of around few kilosamples in order not to extinguish too much RAM memory.
9 | /// - Input sound data is decimated to approx 500 Hz to reduce calculation burden,
10 | /// which is basically ok as low (bass) frequencies mostly determine the beat rate.
11 | /// Simple averaging is used for anti-alias filtering because the resulting signal
12 | /// quality isn't of that high importance.
13 | /// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
14 | /// taking absolute value that's smoothed by sliding average. Signal levels that
15 | /// are below a couple of times the general RMS amplitude level are cut away to
16 | /// leave only notable peaks there.
17 | /// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
18 | /// autocorrelation function of the enveloped signal.
19 | /// - After whole sound data file has been analyzed as above, the bpm level is
20 | /// detected by function 'getBpm' that finds the highest peak of the autocorrelation
21 | /// function, calculates it's precise location and converts this reading to bpm's.
22 | ///
23 | /// Author : Copyright (c) Olli Parviainen
24 | /// Author e-mail : oparviai 'at' iki.fi
25 | /// SoundTouch WWW: http://www.surina.net/soundtouch
26 | ///
27 | ////////////////////////////////////////////////////////////////////////////////
28 | //
29 | // Last changed : $Date: 2016-01-12 19:24:46 +0200 (ti, 12 tammi 2016) $
30 | // File revision : $Revision: 4 $
31 | //
32 | // $Id: BPMDetect.h 239 2016-01-12 17:24:46Z oparviai $
33 | //
34 | ////////////////////////////////////////////////////////////////////////////////
35 | //
36 | // License :
37 | //
38 | // SoundTouch audio processing library
39 | // Copyright (c) Olli Parviainen
40 | //
41 | // This library is free software; you can redistribute it and/or
42 | // modify it under the terms of the GNU Lesser General Public
43 | // License as published by the Free Software Foundation; either
44 | // version 2.1 of the License, or (at your option) any later version.
45 | //
46 | // This library is distributed in the hope that it will be useful,
47 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
48 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
49 | // Lesser General Public License for more details.
50 | //
51 | // You should have received a copy of the GNU Lesser General Public
52 | // License along with this library; if not, write to the Free Software
53 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54 | //
55 | ////////////////////////////////////////////////////////////////////////////////
56 |
57 | #ifndef _BPMDetect_H_
58 | #define _BPMDetect_H_
59 |
60 | #include "STTypes.h"
61 | #include "FIFOSampleBuffer.h"
62 |
63 | namespace soundtouch
64 | {
65 |
66 | /// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
67 | #define MIN_BPM 29
68 |
69 | /// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit.
70 | #define MAX_BPM 200
71 |
72 |
73 | /// Class for calculating BPM rate for audio data.
74 | class BPMDetect
75 | {
76 | protected:
77 | /// Auto-correlation accumulator bins.
78 | float *xcorr;
79 |
80 | /// Sample average counter.
81 | int decimateCount;
82 |
83 | /// Sample average accumulator for FIFO-like decimation.
84 | soundtouch::LONG_SAMPLETYPE decimateSum;
85 |
86 | /// Decimate sound by this coefficient to reach approx. 500 Hz.
87 | int decimateBy;
88 |
89 | /// Auto-correlation window length
90 | int windowLen;
91 |
92 | /// Number of channels (1 = mono, 2 = stereo)
93 | int channels;
94 |
95 | /// sample rate
96 | int sampleRate;
97 |
98 | /// Beginning of auto-correlation window: Autocorrelation isn't being updated for
99 | /// the first these many correlation bins.
100 | int windowStart;
101 |
102 | /// FIFO-buffer for decimated processing samples.
103 | soundtouch::FIFOSampleBuffer *buffer;
104 |
105 | /// Updates auto-correlation function for given number of decimated samples that
106 | /// are read from the internal 'buffer' pipe (samples aren't removed from the pipe
107 | /// though).
108 | void updateXCorr(int process_samples /// How many samples are processed.
109 | );
110 |
111 | /// Decimates samples to approx. 500 Hz.
112 | ///
113 | /// \return Number of output samples.
114 | int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer
115 | const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
116 | int numsamples ///< Number of source samples.
117 | );
118 |
119 | /// Calculates amplitude envelope for the buffer of samples.
120 | /// Result is output to 'samples'.
121 | void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer
122 | int numsamples ///< Number of samples in buffer
123 | );
124 |
125 | /// remove constant bias from xcorr data
126 | void removeBias();
127 |
128 | public:
129 | /// Constructor.
130 | BPMDetect(int numChannels, ///< Number of channels in sample data.
131 | int sampleRate ///< Sample rate in Hz.
132 | );
133 |
134 | /// Destructor.
135 | virtual ~BPMDetect();
136 |
137 | /// Inputs a block of samples for analyzing: Envelopes the samples and then
138 | /// updates the autocorrelation estimation. When whole song data has been input
139 | /// in smaller blocks using this function, read the resulting bpm with 'getBpm'
140 | /// function.
141 | ///
142 | /// Notice that data in 'samples' array can be disrupted in processing.
143 | void inputSamples(const soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer
144 | int numSamples ///< Number of samples in buffer
145 | );
146 |
147 |
148 | /// Analyzes the results and returns the BPM rate. Use this function to read result
149 | /// after whole song data has been input to the class by consecutive calls of
150 | /// 'inputSamples' function.
151 | ///
152 | /// \return Beats-per-minute rate, or zero if detection failed.
153 | float getBpm();
154 | };
155 |
156 | }
157 |
158 | #endif // _BPMDetect_H_
159 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/include/FIFOSampleBuffer.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// A buffer class for temporarily storaging sound samples, operates as a
4 | /// first-in-first-out pipe.
5 | ///
6 | /// Samples are added to the end of the sample buffer with the 'putSamples'
7 | /// function, and are received from the beginning of the buffer by calling
8 | /// the 'receiveSamples' function. The class automatically removes the
9 | /// output samples from the buffer as well as grows the storage size
10 | /// whenever necessary.
11 | ///
12 | /// Author : Copyright (c) Olli Parviainen
13 | /// Author e-mail : oparviai 'at' iki.fi
14 | /// SoundTouch WWW: http://www.surina.net/soundtouch
15 | ///
16 | ////////////////////////////////////////////////////////////////////////////////
17 | //
18 | // Last changed : $Date: 2014-01-05 23:40:22 +0200 (su, 05 tammi 2014) $
19 | // File revision : $Revision: 4 $
20 | //
21 | // $Id: FIFOSampleBuffer.h 177 2014-01-05 21:40:22Z oparviai $
22 | //
23 | ////////////////////////////////////////////////////////////////////////////////
24 | //
25 | // License :
26 | //
27 | // SoundTouch audio processing library
28 | // Copyright (c) Olli Parviainen
29 | //
30 | // This library is free software; you can redistribute it and/or
31 | // modify it under the terms of the GNU Lesser General Public
32 | // License as published by the Free Software Foundation; either
33 | // version 2.1 of the License, or (at your option) any later version.
34 | //
35 | // This library is distributed in the hope that it will be useful,
36 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | // Lesser General Public License for more details.
39 | //
40 | // You should have received a copy of the GNU Lesser General Public
41 | // License along with this library; if not, write to the Free Software
42 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43 | //
44 | ////////////////////////////////////////////////////////////////////////////////
45 |
46 | #ifndef FIFOSampleBuffer_H
47 | #define FIFOSampleBuffer_H
48 |
49 | #include "FIFOSamplePipe.h"
50 |
51 | namespace soundtouch
52 | {
53 |
54 | /// Sample buffer working in FIFO (first-in-first-out) principle. The class takes
55 | /// care of storage size adjustment and data moving during input/output operations.
56 | ///
57 | /// Notice that in case of stereo audio, one sample is considered to consist of
58 | /// both channel data.
59 | class FIFOSampleBuffer : public FIFOSamplePipe
60 | {
61 | private:
62 | /// Sample buffer.
63 | SAMPLETYPE *buffer;
64 |
65 | // Raw unaligned buffer memory. 'buffer' is made aligned by pointing it to first
66 | // 16-byte aligned location of this buffer
67 | SAMPLETYPE *bufferUnaligned;
68 |
69 | /// Sample buffer size in bytes
70 | uint sizeInBytes;
71 |
72 | /// How many samples are currently in buffer.
73 | uint samplesInBuffer;
74 |
75 | /// Channels, 1=mono, 2=stereo.
76 | uint channels;
77 |
78 | /// Current position pointer to the buffer. This pointer is increased when samples are
79 | /// removed from the pipe so that it's necessary to actually rewind buffer (move data)
80 | /// only new data when is put to the pipe.
81 | uint bufferPos;
82 |
83 | /// Rewind the buffer by moving data from position pointed by 'bufferPos' to real
84 | /// beginning of the buffer.
85 | void rewind();
86 |
87 | /// Ensures that the buffer has capacity for at least this many samples.
88 | void ensureCapacity(uint capacityRequirement);
89 |
90 | /// Returns current capacity.
91 | uint getCapacity() const;
92 |
93 | public:
94 |
95 | /// Constructor
96 | FIFOSampleBuffer(int numChannels = 2 ///< Number of channels, 1=mono, 2=stereo.
97 | ///< Default is stereo.
98 | );
99 |
100 | /// destructor
101 | ~FIFOSampleBuffer();
102 |
103 | /// Returns a pointer to the beginning of the output samples.
104 | /// This function is provided for accessing the output samples directly.
105 | /// Please be careful for not to corrupt the book-keeping!
106 | ///
107 | /// When using this function to output samples, also remember to 'remove' the
108 | /// output samples from the buffer by calling the
109 | /// 'receiveSamples(numSamples)' function
110 | virtual SAMPLETYPE *ptrBegin();
111 |
112 | /// Returns a pointer to the end of the used part of the sample buffer (i.e.
113 | /// where the new samples are to be inserted). This function may be used for
114 | /// inserting new samples into the sample buffer directly. Please be careful
115 | /// not corrupt the book-keeping!
116 | ///
117 | /// When using this function as means for inserting new samples, also remember
118 | /// to increase the sample count afterwards, by calling the
119 | /// 'putSamples(numSamples)' function.
120 | SAMPLETYPE *ptrEnd(
121 | uint slackCapacity ///< How much free capacity (in samples) there _at least_
122 | ///< should be so that the caller can succesfully insert the
123 | ///< desired samples to the buffer. If necessary, the function
124 | ///< grows the buffer size to comply with this requirement.
125 | );
126 |
127 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position to
128 | /// the sample buffer.
129 | virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
130 | uint numSamples ///< Number of samples to insert.
131 | );
132 |
133 | /// Adjusts the book-keeping to increase number of samples in the buffer without
134 | /// copying any actual samples.
135 | ///
136 | /// This function is used to update the number of samples in the sample buffer
137 | /// when accessing the buffer directly with 'ptrEnd' function. Please be
138 | /// careful though!
139 | virtual void putSamples(uint numSamples ///< Number of samples been inserted.
140 | );
141 |
142 | /// Output samples from beginning of the sample buffer. Copies requested samples to
143 | /// output buffer and removes them from the sample buffer. If there are less than
144 | /// 'numsample' samples in the buffer, returns all that available.
145 | ///
146 | /// \return Number of samples returned.
147 | virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
148 | uint maxSamples ///< How many samples to receive at max.
149 | );
150 |
151 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
152 | /// sample buffer without copying them anywhere.
153 | ///
154 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
155 | /// with 'ptrBegin' function.
156 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
157 | );
158 |
159 | /// Returns number of samples currently available.
160 | virtual uint numSamples() const;
161 |
162 | /// Sets number of channels, 1 = mono, 2 = stereo.
163 | void setChannels(int numChannels);
164 |
165 | /// Get number of channels
166 | int getChannels()
167 | {
168 | return channels;
169 | }
170 |
171 | /// Returns nonzero if there aren't any samples available for outputting.
172 | virtual int isEmpty() const;
173 |
174 | /// Clears all the samples.
175 | virtual void clear();
176 |
177 | /// allow trimming (downwards) amount of samples in pipeline.
178 | /// Returns adjusted amount of samples
179 | uint adjustAmountOfSamples(uint numSamples);
180 | };
181 |
182 | }
183 |
184 | #endif
185 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/include/FIFOSamplePipe.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// 'FIFOSamplePipe' : An abstract base class for classes that manipulate sound
4 | /// samples by operating like a first-in-first-out pipe: New samples are fed
5 | /// into one end of the pipe with the 'putSamples' function, and the processed
6 | /// samples are received from the other end with the 'receiveSamples' function.
7 | ///
8 | /// 'FIFOProcessor' : A base class for classes the do signal processing with
9 | /// the samples while operating like a first-in-first-out pipe. When samples
10 | /// are input with the 'putSamples' function, the class processes them
11 | /// and moves the processed samples to the given 'output' pipe object, which
12 | /// may be either another processing stage, or a fifo sample buffer object.
13 | ///
14 | /// Author : Copyright (c) Olli Parviainen
15 | /// Author e-mail : oparviai 'at' iki.fi
16 | /// SoundTouch WWW: http://www.surina.net/soundtouch
17 | ///
18 | ////////////////////////////////////////////////////////////////////////////////
19 | //
20 | // Last changed : $Date: 2012-06-13 22:29:53 +0300 (ke, 13 kesä 2012) $
21 | // File revision : $Revision: 4 $
22 | //
23 | // $Id: FIFOSamplePipe.h 143 2012-06-13 19:29:53Z oparviai $
24 | //
25 | ////////////////////////////////////////////////////////////////////////////////
26 | //
27 | // License :
28 | //
29 | // SoundTouch audio processing library
30 | // Copyright (c) Olli Parviainen
31 | //
32 | // This library is free software; you can redistribute it and/or
33 | // modify it under the terms of the GNU Lesser General Public
34 | // License as published by the Free Software Foundation; either
35 | // version 2.1 of the License, or (at your option) any later version.
36 | //
37 | // This library is distributed in the hope that it will be useful,
38 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
39 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 | // Lesser General Public License for more details.
41 | //
42 | // You should have received a copy of the GNU Lesser General Public
43 | // License along with this library; if not, write to the Free Software
44 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 | //
46 | ////////////////////////////////////////////////////////////////////////////////
47 |
48 | #ifndef FIFOSamplePipe_H
49 | #define FIFOSamplePipe_H
50 |
51 | #include
52 | #include
53 | #include "STTypes.h"
54 |
55 | namespace soundtouch
56 | {
57 |
58 | /// Abstract base class for FIFO (first-in-first-out) sample processing classes.
59 | class FIFOSamplePipe
60 | {
61 | public:
62 | // virtual default destructor
63 | virtual ~FIFOSamplePipe() {}
64 |
65 |
66 | /// Returns a pointer to the beginning of the output samples.
67 | /// This function is provided for accessing the output samples directly.
68 | /// Please be careful for not to corrupt the book-keeping!
69 | ///
70 | /// When using this function to output samples, also remember to 'remove' the
71 | /// output samples from the buffer by calling the
72 | /// 'receiveSamples(numSamples)' function
73 | virtual SAMPLETYPE *ptrBegin() = 0;
74 |
75 | /// Adds 'numSamples' pcs of samples from the 'samples' memory position to
76 | /// the sample buffer.
77 | virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
78 | uint numSamples ///< Number of samples to insert.
79 | ) = 0;
80 |
81 |
82 | // Moves samples from the 'other' pipe instance to this instance.
83 | void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data.
84 | )
85 | {
86 | int oNumSamples = other.numSamples();
87 |
88 | putSamples(other.ptrBegin(), oNumSamples);
89 | other.receiveSamples(oNumSamples);
90 | };
91 |
92 | /// Output samples from beginning of the sample buffer. Copies requested samples to
93 | /// output buffer and removes them from the sample buffer. If there are less than
94 | /// 'numsample' samples in the buffer, returns all that available.
95 | ///
96 | /// \return Number of samples returned.
97 | virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
98 | uint maxSamples ///< How many samples to receive at max.
99 | ) = 0;
100 |
101 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
102 | /// sample buffer without copying them anywhere.
103 | ///
104 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
105 | /// with 'ptrBegin' function.
106 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
107 | ) = 0;
108 |
109 | /// Returns number of samples currently available.
110 | virtual uint numSamples() const = 0;
111 |
112 | // Returns nonzero if there aren't any samples available for outputting.
113 | virtual int isEmpty() const = 0;
114 |
115 | /// Clears all the samples.
116 | virtual void clear() = 0;
117 |
118 | /// allow trimming (downwards) amount of samples in pipeline.
119 | /// Returns adjusted amount of samples
120 | virtual uint adjustAmountOfSamples(uint numSamples) = 0;
121 |
122 | };
123 |
124 |
125 |
126 | /// Base-class for sound processing routines working in FIFO principle. With this base
127 | /// class it's easy to implement sound processing stages that can be chained together,
128 | /// so that samples that are fed into beginning of the pipe automatically go through
129 | /// all the processing stages.
130 | ///
131 | /// When samples are input to this class, they're first processed and then put to
132 | /// the FIFO pipe that's defined as output of this class. This output pipe can be
133 | /// either other processing stage or a FIFO sample buffer.
134 | class FIFOProcessor :public FIFOSamplePipe
135 | {
136 | protected:
137 | /// Internal pipe where processed samples are put.
138 | FIFOSamplePipe *output;
139 |
140 | /// Sets output pipe.
141 | void setOutPipe(FIFOSamplePipe *pOutput)
142 | {
143 | assert(output == NULL);
144 | assert(pOutput != NULL);
145 | output = pOutput;
146 | }
147 |
148 |
149 | /// Constructor. Doesn't define output pipe; it has to be set be
150 | /// 'setOutPipe' function.
151 | FIFOProcessor()
152 | {
153 | output = NULL;
154 | }
155 |
156 |
157 | /// Constructor. Configures output pipe.
158 | FIFOProcessor(FIFOSamplePipe *pOutput ///< Output pipe.
159 | )
160 | {
161 | output = pOutput;
162 | }
163 |
164 |
165 | /// Destructor.
166 | virtual ~FIFOProcessor()
167 | {
168 | }
169 |
170 |
171 | /// Returns a pointer to the beginning of the output samples.
172 | /// This function is provided for accessing the output samples directly.
173 | /// Please be careful for not to corrupt the book-keeping!
174 | ///
175 | /// When using this function to output samples, also remember to 'remove' the
176 | /// output samples from the buffer by calling the
177 | /// 'receiveSamples(numSamples)' function
178 | virtual SAMPLETYPE *ptrBegin()
179 | {
180 | return output->ptrBegin();
181 | }
182 |
183 | public:
184 |
185 | /// Output samples from beginning of the sample buffer. Copies requested samples to
186 | /// output buffer and removes them from the sample buffer. If there are less than
187 | /// 'numsample' samples in the buffer, returns all that available.
188 | ///
189 | /// \return Number of samples returned.
190 | virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
191 | uint maxSamples ///< How many samples to receive at max.
192 | )
193 | {
194 | return output->receiveSamples(outBuffer, maxSamples);
195 | }
196 |
197 |
198 | /// Adjusts book-keeping so that given number of samples are removed from beginning of the
199 | /// sample buffer without copying them anywhere.
200 | ///
201 | /// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
202 | /// with 'ptrBegin' function.
203 | virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
204 | )
205 | {
206 | return output->receiveSamples(maxSamples);
207 | }
208 |
209 |
210 | /// Returns number of samples currently available.
211 | virtual uint numSamples() const
212 | {
213 | return output->numSamples();
214 | }
215 |
216 |
217 | /// Returns nonzero if there aren't any samples available for outputting.
218 | virtual int isEmpty() const
219 | {
220 | return output->isEmpty();
221 | }
222 |
223 | /// allow trimming (downwards) amount of samples in pipeline.
224 | /// Returns adjusted amount of samples
225 | virtual uint adjustAmountOfSamples(uint numSamples)
226 | {
227 | return output->adjustAmountOfSamples(numSamples);
228 | }
229 |
230 | };
231 |
232 | }
233 |
234 | #endif
235 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/include/Makefile.am:
--------------------------------------------------------------------------------
1 | ## Process this file with automake to create Makefile.in
2 | ##
3 | ## $Id: Makefile.am 11 2008-02-10 16:26:55Z oparviai $
4 | ##
5 | ## Copyright (C) 2003 - David W. Durham
6 | ##
7 | ## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
8 | ##
9 | ## SoundTouch is free software; you can redistribute it and/or modify it under the
10 | ## terms of the GNU General Public License as published by the Free Software
11 | ## Foundation; either version 2 of the License, or (at your option) any later
12 | ## version.
13 | ##
14 | ## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY
15 | ## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 | ## A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 | ##
18 | ## You should have received a copy of the GNU General Public License along with
19 | ## this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 | ## Place - Suite 330, Boston, MA 02111-1307, USA
21 |
22 | ## I used config/am_include.mk for common definitions
23 | include $(top_srcdir)/config/am_include.mk
24 |
25 | pkginclude_HEADERS=FIFOSampleBuffer.h FIFOSamplePipe.h SoundTouch.h STTypes.h BPMDetect.h soundtouch_config.h
26 |
27 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/include/STTypes.h:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////
2 | ///
3 | /// Common type definitions for SoundTouch audio processing library.
4 | ///
5 | /// Author : Copyright (c) Olli Parviainen
6 | /// Author e-mail : oparviai 'at' iki.fi
7 | /// SoundTouch WWW: http://www.surina.net/soundtouch
8 | ///
9 | ////////////////////////////////////////////////////////////////////////////////
10 | //
11 | // Last changed : $Date: 2017-07-30 12:28:06 +0300 (su, 30 heinä 2017) $
12 | // File revision : $Revision: 3 $
13 | //
14 | // $Id: STTypes.h 252 2017-07-30 09:28:06Z oparviai $
15 | //
16 | ////////////////////////////////////////////////////////////////////////////////
17 | //
18 | // License :
19 | //
20 | // SoundTouch audio processing library
21 | // Copyright (c) Olli Parviainen
22 | //
23 | // This library is free software; you can redistribute it and/or
24 | // modify it under the terms of the GNU Lesser General Public
25 | // License as published by the Free Software Foundation; either
26 | // version 2.1 of the License, or (at your option) any later version.
27 | //
28 | // This library is distributed in the hope that it will be useful,
29 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
30 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 | // Lesser General Public License for more details.
32 | //
33 | // You should have received a copy of the GNU Lesser General Public
34 | // License along with this library; if not, write to the Free Software
35 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 | //
37 | ////////////////////////////////////////////////////////////////////////////////
38 |
39 | #ifndef STTypes_H
40 | #define STTypes_H
41 |
42 | typedef unsigned int uint;
43 | typedef unsigned long ulong;
44 |
45 | // Patch for MinGW: on Win64 long is 32-bit
46 | #ifdef _WIN64
47 | typedef unsigned long long ulongptr;
48 | #else
49 | typedef ulong ulongptr;
50 | #endif
51 |
52 |
53 | // Helper macro for aligning pointer up to next 16-byte boundary
54 | #define SOUNDTOUCH_ALIGN_POINTER_16(x) ( ( (ulongptr)(x) + 15 ) & ~(ulongptr)15 )
55 |
56 |
57 | #if (defined(__GNUC__) && !defined(ANDROID))
58 | // In GCC, include soundtouch_config.h made by config scritps.
59 | // Skip this in Android compilation that uses GCC but without configure scripts.
60 | #include "soundtouch_config.h"
61 | #endif
62 |
63 |
64 | namespace soundtouch
65 | {
66 | /// Activate these undef's to overrule the possible sampletype
67 | /// setting inherited from some other header file:
68 | //#undef SOUNDTOUCH_INTEGER_SAMPLES
69 | #undef SOUNDTOUCH_FLOAT_SAMPLES
70 |
71 | /// If following flag is defined, always uses multichannel processing
72 | /// routines also for mono and stero sound. This is for routine testing
73 | /// purposes; output should be same with either routines, yet disabling
74 | /// the dedicated mono/stereo processing routines will result in slower
75 | /// runtime performance so recommendation is to keep this off.
76 | // #define USE_MULTICH_ALWAYS
77 |
78 | #if (defined(__SOFTFP__) && defined(ANDROID))
79 | // For Android compilation: Force use of Integer samples in case that
80 | // compilation uses soft-floating point emulation - soft-fp is way too slow
81 | #undef SOUNDTOUCH_FLOAT_SAMPLES
82 | #define SOUNDTOUCH_INTEGER_SAMPLES 1
83 | #endif
84 |
85 | #if !(SOUNDTOUCH_INTEGER_SAMPLES || SOUNDTOUCH_FLOAT_SAMPLES)
86 |
87 | /// Choose either 32bit floating point or 16bit integer sampletype
88 | /// by choosing one of the following defines, unless this selection
89 | /// has already been done in some other file.
90 | ////
91 | /// Notes:
92 | /// - In Windows environment, choose the sample format with the
93 | /// following defines.
94 | /// - In GNU environment, the floating point samples are used by
95 | /// default, but integer samples can be chosen by giving the
96 | /// following switch to the configure script:
97 | /// ./configure --enable-integer-samples
98 | /// However, if you still prefer to select the sample format here
99 | /// also in GNU environment, then please #undef the INTEGER_SAMPLE
100 | /// and FLOAT_SAMPLE defines first as in comments above.
101 | #define SOUNDTOUCH_INTEGER_SAMPLES 1 //< 16bit integer samples
102 | // #define SOUNDTOUCH_FLOAT_SAMPLES 1 //< 32bit float samples
103 |
104 | #endif
105 |
106 | #if (_M_IX86 || __i386__ || __x86_64__ || _M_X64)
107 | /// Define this to allow X86-specific assembler/intrinsic optimizations.
108 | /// Notice that library contains also usual C++ versions of each of these
109 | /// these routines, so if you're having difficulties getting the optimized
110 | /// routines compiled for whatever reason, you may disable these optimizations
111 | /// to make the library compile.
112 |
113 | #define SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS 1
114 |
115 | /// In GNU environment, allow the user to override this setting by
116 | /// giving the following switch to the configure script:
117 | /// ./configure --disable-x86-optimizations
118 | /// ./configure --enable-x86-optimizations=no
119 | #ifdef SOUNDTOUCH_DISABLE_X86_OPTIMIZATIONS
120 | #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
121 | #endif
122 | #else
123 | /// Always disable optimizations when not using a x86 systems.
124 | #undef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
125 |
126 | #endif
127 |
128 | // If defined, allows the SIMD-optimized routines to take minor shortcuts
129 | // for improved performance. Undefine to require faithfully similar SIMD
130 | // calculations as in normal C implementation.
131 | #define SOUNDTOUCH_ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
132 |
133 |
134 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES
135 | // 16bit integer sample type
136 | typedef short SAMPLETYPE;
137 | // data type for sample accumulation: Use 32bit integer to prevent overflows
138 | typedef long LONG_SAMPLETYPE;
139 |
140 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES
141 | // check that only one sample type is defined
142 | #error "conflicting sample types defined"
143 | #endif // SOUNDTOUCH_FLOAT_SAMPLES
144 |
145 | #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
146 | // Allow MMX optimizations (not available in X64 mode)
147 | #if (!_M_X64)
148 | #define SOUNDTOUCH_ALLOW_MMX 1
149 | #endif
150 | #endif
151 |
152 | #else
153 |
154 | // floating point samples
155 | typedef float SAMPLETYPE;
156 | // data type for sample accumulation: Use double to utilize full precision.
157 | typedef double LONG_SAMPLETYPE;
158 |
159 | #ifdef SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS
160 | // Allow SSE optimizations
161 | #define SOUNDTOUCH_ALLOW_SSE 1
162 | #endif
163 |
164 | #endif // SOUNDTOUCH_INTEGER_SAMPLES
165 |
166 | };
167 |
168 | // define ST_NO_EXCEPTION_HANDLING switch to disable throwing std exceptions:
169 | // #define ST_NO_EXCEPTION_HANDLING 1
170 | #ifdef ST_NO_EXCEPTION_HANDLING
171 | // Exceptions disabled. Throw asserts instead if enabled.
172 | #include
173 | #define ST_THROW_RT_ERROR(x) {assert((const char *)x);}
174 | #else
175 | // use c++ standard exceptions
176 | #include
177 | #include
178 | #define ST_THROW_RT_ERROR(x) {throw std::runtime_error(x);}
179 | #endif
180 |
181 | // When this #define is active, eliminates a clicking sound when the "rate" or "pitch"
182 | // parameter setting crosses from value <1 to >=1 or vice versa during processing.
183 | // Default is off as such crossover is untypical case and involves a slight sound
184 | // quality compromise.
185 | //#define SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER 1
186 |
187 | #endif
188 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/SoundTouch/include/soundtouch_config.h.in:
--------------------------------------------------------------------------------
1 | /* Use Float as Sample type */
2 | #undef SOUNDTOUCH_FLOAT_SAMPLES
3 |
4 | /* Use Integer as Sample type */
5 | #undef SOUNDTOUCH_INTEGER_SAMPLES
6 |
--------------------------------------------------------------------------------
/soundtouch/src/main/cpp/common.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Junyue Cao on 16/5/25.
3 | //
4 |
5 | #ifndef LIB_NATIVE_COMMON_H
6 | #define LIB_NATIVE_COMMON_H
7 |
8 | #if defined(__arm__)
9 | #if defined(__ARM_ARCH_7A__)
10 | #if defined(__ARM_NEON__)
11 | #define ABI "armeabi-v7a/NEON"
12 | #else
13 | #define ABI "armeabi-v7a"
14 | #endif
15 | #else
16 | #define ABI "armeabi"
17 | #endif
18 | #elif defined(__i386__)
19 | #define ABI "x86"
20 | #elif defined(__mips__)
21 | #define ABI "mips"
22 | #else
23 | #define ABI "unknown"
24 | #endif
25 |
26 | #endif //LIB_NATIVE_COMMON_H
27 | #ifndef NELEM
28 | # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
29 | #endif
30 | #ifdef __LP64__
31 | #define __PRI_64_prefix "l"
32 | #define __PRI_PTR_prefix "l"
33 | #else
34 | #define __PRI_64_prefix "ll"
35 | #define __PRI_PTR_prefix
36 | #endif
37 | #ifndef SCNu64
38 | #define SCNu64 __PRI_64_prefix"u" /* uint64_t */
39 | #endif
40 | #ifndef SCNx64
41 | #define SCNx64 __PRI_64_prefix"x" /* uint64_t */
42 | #endif
43 | #ifndef SCNu32
44 | #define SCNu32 "u" /* uint32_t */
45 | #endif
46 |
47 | //Log
48 | #ifdef ANDROID
49 | #include
50 | #include
51 | #define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
52 | #define LOGD(format, ...) __android_log_print(ANDROID_LOG_DEBUG, "LOGD", format, ##__VA_ARGS__)
53 | #define LOGI(format, ...) __android_log_print(ANDROID_LOG_INFO, "(^_^)", format, ##__VA_ARGS__)
54 | #else
55 | #define LOGE(format, ...) printf("(>_<) " format "\n", ##__VA_ARGS__)
56 | #define LOGI(format, ...) printf("(^_^) " format "\n", ##__VA_ARGS__)
57 | #endif
58 |
--------------------------------------------------------------------------------
/soundtouch/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SoundTouchJava
3 |
4 |
--------------------------------------------------------------------------------
/soundtouch/src/test/java/io/github/junyuecao/soundtouch/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package io.github.junyuecao.soundtouch;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------