├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── xyz
│ │ └── gianlu
│ │ └── librespot
│ │ └── android
│ │ ├── LibrespotApp.java
│ │ ├── LibrespotHolder.java
│ │ ├── LoginActivity.java
│ │ ├── MainActivity.java
│ │ └── Utils.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_login.xml
│ └── activity_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── values-night
│ └── themes.xml
│ ├── values
│ ├── colors.xml
│ ├── strings.xml
│ └── themes.xml
│ └── xml
│ └── backup_descriptor.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── librespot-android-decoder-tremolo
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── .gitignore
│ ├── AndroidManifest.xml
│ ├── java
│ └── xyz
│ │ └── gianlu
│ │ └── librespot
│ │ └── player
│ │ └── decoders
│ │ ├── TremoloVorbisDecoder.java
│ │ └── tremolo
│ │ ├── OggDecodingInputStream.java
│ │ └── SeekableInputStream.java
│ ├── jni
│ ├── Android.mk
│ ├── Application.mk
│ └── libtremolo
│ │ ├── Android.mk
│ │ ├── asm_arm.h
│ │ ├── bitwise.c
│ │ ├── bitwiseARM.s
│ │ ├── codebook.c
│ │ ├── codebook.h
│ │ ├── codec_internal.h
│ │ ├── config_types.h
│ │ ├── dpen.s
│ │ ├── dsp.c
│ │ ├── floor0.c
│ │ ├── floor1.c
│ │ ├── floor1ARM.s
│ │ ├── floor_lookup.c
│ │ ├── framing.c
│ │ ├── hide.c
│ │ ├── hide.h
│ │ ├── ivorbiscodec.h
│ │ ├── ivorbisfile.h
│ │ ├── lsp_lookup.h
│ │ ├── mapping0.c
│ │ ├── md5.c
│ │ ├── md5.h
│ │ ├── mdct.c
│ │ ├── mdct.h
│ │ ├── mdctARM.s
│ │ ├── mdct_lookup.h
│ │ ├── misc.c
│ │ ├── misc.h
│ │ ├── ogg.h
│ │ ├── os.h
│ │ ├── os_types.h
│ │ ├── res012.c
│ │ ├── treminfo.c
│ │ ├── tremolo-jni.c
│ │ ├── vorbisfile.c
│ │ └── window_lookup.h
│ └── libs
│ ├── arm64-v8a
│ └── libtremolo.so
│ └── armeabi-v7a
│ └── libtremolo.so
├── librespot-android-decoder
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── xyz
│ └── gianlu
│ └── librespot
│ └── player
│ └── decoders
│ └── AndroidNativeDecoder.java
├── librespot-android-sink
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── xyz
│ │ └── gianlu
│ │ └── librespot
│ │ └── android
│ │ └── sink
│ │ ├── AudioStreamInstrumentedTest.java
│ │ └── ToneGenerator.java
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── xyz
│ └── gianlu
│ └── librespot
│ └── android
│ └── sink
│ └── AndroidSinkOutput.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /.idea
3 | .DS_Store
4 | /build
5 | /captures
6 | .cxx
7 |
8 | # Built application files
9 | *.apk
10 | *.aar
11 | *.ap_
12 | *.aab
13 |
14 | # Files for the ART/Dalvik VM
15 | *.dex
16 |
17 | # Java class files
18 | *.class
19 |
20 | # Generated files
21 | bin/
22 | gen/
23 | out/
24 | # Uncomment the following line in case you need and you don't have the release build type files in your app
25 | # release/
26 |
27 | # Gradle files
28 | .gradle/
29 | build/
30 |
31 | # Local configuration file (sdk path, etc)
32 | local.properties
33 |
34 | # Proguard folder generated by Eclipse
35 | proguard/
36 |
37 | # Log Files
38 | *.log
39 |
40 | # Android Studio Navigation editor temp files
41 | .navigation/
42 |
43 | # Android Studio captures folder
44 | captures/
45 |
46 | # IntelliJ
47 | *.iml
48 | .idea/workspace.xml
49 | .idea/tasks.xml
50 | .idea/gradle.xml
51 | .idea/assetWizardSettings.xml
52 | .idea/dictionaries
53 | .idea/libraries
54 | # Android Studio 3 in .gitignore file.
55 | .idea/caches
56 | .idea/modules.xml
57 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
58 | .idea/navEditor.xml
59 |
60 | # Keystore files
61 | # Uncomment the following lines if you do not want to check your keystore files in.
62 | #*.jks
63 | #*.keystore
64 |
65 | # External native build folder generated in Android Studio 2.2 and later
66 | .externalNativeBuild
67 | .cxx/
68 |
69 | # Google Services (e.g. APIs or Firebase)
70 | # google-services.json
71 |
72 | # Freeline
73 | freeline.py
74 | freeline/
75 | freeline_project_description.json
76 |
77 | # fastlane
78 | fastlane/report.xml
79 | fastlane/Preview.html
80 | fastlane/screenshots
81 | fastlane/test_output
82 | fastlane/readme.md
83 |
84 | # Version control
85 | vcs.xml
86 |
87 | # lint
88 | lint/intermediates/
89 | lint/generated/
90 | lint/outputs/
91 | lint/tmp/
92 | # lint/reports/
93 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # librespot-android
2 |
3 | This is a demo application to demonstrate that it is possible to run [librespot-java](https://github.com/librespot-org/librespot-java) on an Android device. The app provides basic functionalities to login and then to play a custom URI, pause/resume, skip next and previous, but all features could be implemented.
4 |
5 | This repo also contains some useful modules that contain Android-compatible sinks and decoders that you might want to use in your app.
6 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdkVersion 31
7 | buildToolsVersion "30.0.3"
8 |
9 | defaultConfig {
10 | applicationId "xyz.gianlu.librespot.android"
11 | minSdkVersion 23
12 | targetSdkVersion 31
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 |
24 | buildFeatures {
25 | viewBinding true
26 | }
27 |
28 | compileOptions {
29 | // Flag to enable support for the new language APIs
30 | coreLibraryDesugaringEnabled true
31 |
32 | sourceCompatibility JavaVersion.VERSION_1_8
33 | targetCompatibility JavaVersion.VERSION_1_8
34 | }
35 |
36 | packagingOptions {
37 | exclude 'log4j2.xml'
38 | exclude 'META-INF/DEPENDENCIES'
39 | }
40 | }
41 |
42 | dependencies {
43 | coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
44 |
45 | implementation 'androidx.appcompat:appcompat:1.4.0'
46 | implementation 'com.google.android.material:material:1.4.0'
47 |
48 | implementation('xyz.gianlu.librespot:librespot-player:1.6.2:thin') {
49 | exclude group: 'xyz.gianlu.librespot', module: 'librespot-sink'
50 | exclude group: 'com.lmax', module: 'disruptor'
51 | exclude group: 'org.apache.logging.log4j'
52 | }
53 |
54 | implementation project(':librespot-android-decoder')
55 | implementation project(':librespot-android-decoder-tremolo')
56 | implementation project(':librespot-android-sink')
57 | implementation 'uk.uuid.slf4j:slf4j-android:1.7.30-0'
58 | }
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/gianlu/librespot/android/LibrespotApp.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android;
2 |
3 | import android.app.Application;
4 | import android.os.Build;
5 | import android.util.Log;
6 |
7 | import xyz.gianlu.librespot.audio.decoders.Decoders;
8 | import xyz.gianlu.librespot.audio.format.SuperAudioFormat;
9 | import xyz.gianlu.librespot.player.decoders.AndroidNativeDecoder;
10 | import xyz.gianlu.librespot.player.decoders.TremoloVorbisDecoder;
11 |
12 | public final class LibrespotApp extends Application {
13 | private static final String TAG = LibrespotApp.class.getSimpleName();
14 |
15 | static {
16 | Decoders.registerDecoder(SuperAudioFormat.VORBIS, 0, AndroidNativeDecoder.class);
17 | Decoders.registerDecoder(SuperAudioFormat.MP3, 0, AndroidNativeDecoder.class);
18 |
19 | if (isArm()) {
20 | Decoders.registerDecoder(SuperAudioFormat.VORBIS, 0, TremoloVorbisDecoder.class);
21 | Log.i(TAG, "Using ARM optimized Vorbis decoder");
22 | }
23 | }
24 |
25 | private static boolean isArm() {
26 | for (String abi : Build.SUPPORTED_ABIS)
27 | if (abi.contains("arm"))
28 | return true;
29 |
30 | return false;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/gianlu/librespot/android/LibrespotHolder.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import java.io.IOException;
8 | import java.lang.ref.WeakReference;
9 |
10 | import xyz.gianlu.librespot.core.Session;
11 | import xyz.gianlu.librespot.player.Player;
12 |
13 | public final class LibrespotHolder {
14 | private volatile static WeakReference session;
15 | private volatile static WeakReference player;
16 |
17 | private LibrespotHolder() {
18 | }
19 |
20 | public static void set(@NotNull Session session) {
21 | LibrespotHolder.session = new WeakReference<>(session);
22 | }
23 |
24 | public static void set(@NotNull Player player) {
25 | LibrespotHolder.player = new WeakReference<>(player);
26 | }
27 |
28 | public static void clear() {
29 | Session s = getSession();
30 | Player p = getPlayer();
31 | if (p != null || s != null) {
32 | new Thread(() -> {
33 | if (p != null) p.close();
34 |
35 | try {
36 | if (s != null) s.close();
37 | } catch (IOException ignored) {
38 | }
39 | }).start();
40 | }
41 |
42 | player = null;
43 | session = null;
44 | }
45 |
46 | @Nullable
47 | public static Session getSession() {
48 | return session != null ? session.get() : null;
49 | }
50 |
51 | @Nullable
52 | public static Player getPlayer() {
53 | return player != null ? player.get() : null;
54 | }
55 |
56 | public static boolean hasSession() {
57 | return getSession() != null;
58 | }
59 |
60 | public static boolean hasPlayer() {
61 | return getPlayer() != null;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/gianlu/librespot/android/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.util.Log;
8 | import android.widget.Toast;
9 |
10 | import androidx.annotation.UiThread;
11 | import androidx.appcompat.app.AppCompatActivity;
12 |
13 | import com.spotify.connectstate.Connect;
14 |
15 | import org.jetbrains.annotations.NotNull;
16 |
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.security.GeneralSecurityException;
20 | import java.util.Locale;
21 |
22 | import xyz.gianlu.librespot.android.databinding.ActivityLoginBinding;
23 | import xyz.gianlu.librespot.core.Session;
24 | import xyz.gianlu.librespot.mercury.MercuryClient;
25 |
26 | public final class LoginActivity extends AppCompatActivity {
27 | private static final String TAG = LoginActivity.class.getSimpleName();
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | ActivityLoginBinding binding = ActivityLoginBinding.inflate(getLayoutInflater());
33 | setContentView(binding.getRoot());
34 |
35 | LoginCallback callback = new LoginCallback() {
36 | @Override
37 | public void loggedIn() {
38 | Toast.makeText(LoginActivity.this, R.string.loggedIn, Toast.LENGTH_SHORT).show();
39 | startActivity(new Intent(LoginActivity.this, MainActivity.class)
40 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
41 | }
42 |
43 | @Override
44 | public void failedLoggingIn(@NotNull Exception ex) {
45 | Toast.makeText(LoginActivity.this, R.string.failedLoggingIn, Toast.LENGTH_SHORT).show();
46 | }
47 | };
48 |
49 | binding.login.setOnClickListener(v -> {
50 | String username = Utils.getText(binding.username);
51 | String password = Utils.getText(binding.password);
52 | if (username.isEmpty() || password.isEmpty())
53 | return;
54 |
55 | File credentialsFile = Utils.getCredentialsFile(this);
56 | new LoginThread(username, password, credentialsFile, callback).start();
57 | });
58 | }
59 |
60 | @UiThread
61 | private interface LoginCallback {
62 | void loggedIn();
63 |
64 | void failedLoggingIn(@NotNull Exception ex);
65 | }
66 |
67 | private static class LoginThread extends Thread {
68 | private final String username;
69 | private final String password;
70 | private final File credentialsFile;
71 | private final LoginCallback callback;
72 | private final Handler handler;
73 |
74 | LoginThread(String username, String password, File credentialsFile, LoginCallback callback) {
75 | this.username = username;
76 | this.password = password;
77 | this.credentialsFile = credentialsFile;
78 | this.callback = callback;
79 | this.handler = new Handler(Looper.getMainLooper());
80 | }
81 |
82 | @Override
83 | public void run() {
84 | try {
85 | Session.Configuration conf = new Session.Configuration.Builder()
86 | .setStoreCredentials(true)
87 | .setStoredCredentialsFile(credentialsFile)
88 | .setCacheEnabled(false)
89 | .build();
90 |
91 | Session.Builder builder = new Session.Builder(conf)
92 | .setPreferredLocale(Locale.getDefault().getLanguage())
93 | .setDeviceType(Connect.DeviceType.SMARTPHONE)
94 | .setDeviceId(null).setDeviceName("librespot-android");
95 |
96 | Session session = builder.userPass(username, password).create();
97 | Log.i(TAG, "Logged in as: " + session.username());
98 |
99 | LibrespotHolder.set(session);
100 |
101 | handler.post(callback::loggedIn);
102 | } catch (IOException |
103 | GeneralSecurityException |
104 | Session.SpotifyAuthenticationException |
105 | MercuryClient.MercuryException ex) {
106 | Log.e(TAG, "Session creation failed!", ex);
107 | handler.post(() -> callback.failedLoggingIn(ex));
108 | }
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/app/src/main/java/xyz/gianlu/librespot/android/MainActivity.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android;
2 |
3 | import android.content.Intent;
4 | import android.os.Build;
5 | import android.os.Bundle;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.Toast;
11 |
12 | import androidx.annotation.Nullable;
13 | import androidx.annotation.UiThread;
14 | import androidx.appcompat.app.AppCompatActivity;
15 |
16 | import com.spotify.connectstate.Connect;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.security.GeneralSecurityException;
23 | import java.util.Locale;
24 | import java.util.concurrent.ExecutorService;
25 | import java.util.concurrent.Executors;
26 |
27 | import xyz.gianlu.librespot.android.databinding.ActivityMainBinding;
28 | import xyz.gianlu.librespot.android.sink.AndroidSinkOutput;
29 | import xyz.gianlu.librespot.core.Session;
30 | import xyz.gianlu.librespot.mercury.MercuryClient;
31 | import xyz.gianlu.librespot.player.Player;
32 | import xyz.gianlu.librespot.player.PlayerConfiguration;
33 |
34 | public final class MainActivity extends AppCompatActivity {
35 | private static final String TAG = MainActivity.class.getSimpleName();
36 | private final ExecutorService executorService = Executors.newSingleThreadExecutor();
37 |
38 | @Override
39 | protected void onDestroy() {
40 | super.onDestroy();
41 | LibrespotHolder.clear();
42 | }
43 |
44 | @Override
45 | protected void onCreate(@Nullable Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
48 | setContentView(binding.getRoot());
49 |
50 | File credentialsFile = Utils.getCredentialsFile(this);
51 | if (!credentialsFile.exists() || !credentialsFile.canRead()) {
52 | startActivity(new Intent(this, LoginActivity.class)
53 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
54 | return;
55 | }
56 |
57 | binding.logout.setOnClickListener(v -> {
58 | credentialsFile.delete();
59 | LibrespotHolder.clear();
60 | startActivity(new Intent(MainActivity.this, LoginActivity.class)
61 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
62 | });
63 |
64 | binding.play.setOnClickListener((v) -> {
65 | String playUri = Utils.getText(binding.playUri);
66 | if (playUri.isEmpty())
67 | return;
68 |
69 | executorService.execute(new PlayRunnable(playUri, () -> Toast.makeText(MainActivity.this, R.string.playbackStarted, Toast.LENGTH_SHORT).show()));
70 | });
71 |
72 | binding.resume.setOnClickListener((v) ->
73 | executorService.execute(new ResumeRunnable(() ->
74 | Toast.makeText(this, R.string.resumed, Toast.LENGTH_SHORT).show())));
75 |
76 | binding.pause.setOnClickListener((v) ->
77 | executorService.execute(new PauseRunnable(() ->
78 | Toast.makeText(this, R.string.paused, Toast.LENGTH_SHORT).show())));
79 |
80 | binding.prev.setOnClickListener((v) ->
81 | executorService.execute(new PrevRunnable(() ->
82 | Toast.makeText(this, R.string.skippedPrev, Toast.LENGTH_SHORT).show())));
83 |
84 | binding.next.setOnClickListener((v) ->
85 | executorService.execute(new NextRunnable(() ->
86 | Toast.makeText(this, R.string.skippedNext, Toast.LENGTH_SHORT).show())));
87 |
88 | executorService.submit(new SetupRunnable(credentialsFile, new SetupCallback() {
89 | @Override
90 | public void playerReady(@NotNull String username) {
91 | Toast.makeText(MainActivity.this, R.string.playerReady, Toast.LENGTH_SHORT).show();
92 | binding.username.setText(username);
93 | binding.playControls.setVisibility(View.VISIBLE);
94 | }
95 |
96 | @Override
97 | public void notLoggedIn() {
98 | startActivity(new Intent(MainActivity.this, LoginActivity.class)
99 | .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
100 | }
101 |
102 | @Override
103 | public void failedGettingReady(@NotNull Exception ex) {
104 | Toast.makeText(MainActivity.this, R.string.somethingWentWrong, Toast.LENGTH_SHORT).show();
105 | binding.playControls.setVisibility(View.GONE);
106 | }
107 | }));
108 | }
109 |
110 | @UiThread
111 | private interface SetupCallback {
112 | void playerReady(@NotNull String username);
113 |
114 | void notLoggedIn();
115 |
116 | void failedGettingReady(@NotNull Exception ex);
117 | }
118 |
119 | private interface SimpleCallback {
120 | void done();
121 | }
122 |
123 | private static class SetupRunnable implements Runnable {
124 | private final File credentialsFile;
125 | private final SetupCallback callback;
126 | private final Handler handler;
127 |
128 | SetupRunnable(@NotNull File credentialsFile, @NotNull SetupCallback callback) {
129 | this.credentialsFile = credentialsFile;
130 | this.callback = callback;
131 | this.handler = new Handler(Looper.getMainLooper());
132 | }
133 |
134 | @Override
135 | public void run() {
136 | Session session;
137 | if (LibrespotHolder.hasSession()) {
138 | session = LibrespotHolder.getSession();
139 | if (session == null) throw new IllegalStateException();
140 | } else if (credentialsFile.exists() && credentialsFile.canRead()) {
141 | try {
142 | Session.Configuration conf = new Session.Configuration.Builder()
143 | .setStoreCredentials(true)
144 | .setStoredCredentialsFile(credentialsFile)
145 | .setCacheEnabled(false)
146 | .build();
147 |
148 | Session.Builder builder = new Session.Builder(conf)
149 | .setPreferredLocale(Locale.getDefault().getLanguage())
150 | .setDeviceType(Connect.DeviceType.SMARTPHONE)
151 | .setDeviceId(null).setDeviceName("librespot-android");
152 |
153 | session = builder.stored(credentialsFile).create();
154 | Log.i(TAG, "Logged in as: " + session.username());
155 |
156 | LibrespotHolder.set(session);
157 | } catch (IOException |
158 | GeneralSecurityException |
159 | Session.SpotifyAuthenticationException |
160 | MercuryClient.MercuryException ex) {
161 | Log.e(TAG, "Session creation failed!", ex);
162 | handler.post(() -> callback.failedGettingReady(ex));
163 | return;
164 | }
165 | } else {
166 | handler.post(callback::notLoggedIn);
167 | return;
168 | }
169 |
170 | Player player;
171 | if (LibrespotHolder.hasPlayer()) {
172 | player = LibrespotHolder.getPlayer();
173 | if (player == null) throw new IllegalStateException();
174 | } else {
175 | PlayerConfiguration configuration = new PlayerConfiguration.Builder()
176 | .setOutput(PlayerConfiguration.AudioOutput.CUSTOM)
177 | .setOutputClass(AndroidSinkOutput.class.getName())
178 | .build();
179 |
180 | player = new Player(configuration, session);
181 | LibrespotHolder.set(player);
182 | }
183 |
184 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
185 | while (!player.isReady()) {
186 | try {
187 | //noinspection BusyWait
188 | Thread.sleep(100);
189 | } catch (InterruptedException ex) {
190 | return;
191 | }
192 | }
193 | } else {
194 | try {
195 | player.waitReady();
196 | } catch (InterruptedException ex) {
197 | LibrespotHolder.clear();
198 | return;
199 | }
200 | }
201 |
202 | handler.post(() -> callback.playerReady(session.username()));
203 | }
204 | }
205 |
206 | private static class PlayRunnable implements Runnable {
207 | private final String playUri;
208 | private final SimpleCallback callback;
209 | private final Handler handler = new Handler(Looper.getMainLooper());
210 |
211 | PlayRunnable(@NotNull String playUri, @NotNull SimpleCallback callback) {
212 | this.playUri = playUri;
213 | this.callback = callback;
214 | }
215 |
216 | @Override
217 | public void run() {
218 | Player player = LibrespotHolder.getPlayer();
219 | if (player == null) return;
220 |
221 | player.load(playUri, true, false);
222 | handler.post(callback::done);
223 | }
224 | }
225 |
226 | private static class ResumeRunnable implements Runnable {
227 | private final SimpleCallback callback;
228 | private final Handler handler = new Handler(Looper.getMainLooper());
229 |
230 | ResumeRunnable(@NotNull SimpleCallback callback) {
231 | this.callback = callback;
232 | }
233 |
234 | @Override
235 | public void run() {
236 | Player player = LibrespotHolder.getPlayer();
237 | if (player == null) return;
238 |
239 | player.play();
240 | handler.post(callback::done);
241 | }
242 | }
243 |
244 | private static class PauseRunnable implements Runnable {
245 | private final SimpleCallback callback;
246 | private final Handler handler = new Handler(Looper.getMainLooper());
247 |
248 | PauseRunnable(@NotNull SimpleCallback callback) {
249 | this.callback = callback;
250 | }
251 |
252 | @Override
253 | public void run() {
254 | Player player = LibrespotHolder.getPlayer();
255 | if (player == null) return;
256 |
257 | player.pause();
258 | handler.post(callback::done);
259 | }
260 | }
261 |
262 | private static class PrevRunnable implements Runnable {
263 | private final SimpleCallback callback;
264 | private final Handler handler = new Handler(Looper.getMainLooper());
265 |
266 | PrevRunnable(@NotNull SimpleCallback callback) {
267 | this.callback = callback;
268 | }
269 |
270 | @Override
271 | public void run() {
272 | Player player = LibrespotHolder.getPlayer();
273 | if (player == null) return;
274 |
275 | player.previous();
276 | handler.post(callback::done);
277 | }
278 | }
279 |
280 | private static class NextRunnable implements Runnable {
281 | private final SimpleCallback callback;
282 | private final Handler handler = new Handler(Looper.getMainLooper());
283 |
284 | NextRunnable(@NotNull SimpleCallback callback) {
285 | this.callback = callback;
286 | }
287 |
288 | @Override
289 | public void run() {
290 | Player player = LibrespotHolder.getPlayer();
291 | if (player == null) return;
292 |
293 | player.next();
294 | handler.post(callback::done);
295 | }
296 | }
297 | }
298 |
--------------------------------------------------------------------------------
/app/src/main/java/xyz/gianlu/librespot/android/Utils.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android;
2 |
3 | import android.content.Context;
4 | import android.widget.EditText;
5 |
6 | import com.google.android.material.textfield.TextInputLayout;
7 |
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.io.File;
11 |
12 | public final class Utils {
13 |
14 | private Utils() {
15 | }
16 |
17 | @NotNull
18 | public static String getText(@NotNull TextInputLayout layout) {
19 | EditText editText = layout.getEditText();
20 | if (editText == null) throw new IllegalStateException();
21 | return editText.getText().toString();
22 | }
23 |
24 | @NotNull
25 | public static File getCredentialsFile(@NotNull Context context) {
26 | return new File(context.getCacheDir(), "credentials.json");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
21 |
27 |
28 |
32 |
33 |
34 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
18 |
19 |
26 |
27 |
33 |
34 |
40 |
41 |
42 |
48 |
49 |
54 |
55 |
60 |
61 |
66 |
67 |
72 |
73 |
--------------------------------------------------------------------------------
/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/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | librespot-android
3 | Username
4 | Password
5 | Login
6 | Logged in!
7 | Failed logging in!
8 | Playback started!
9 | Failed starting playback!
10 | Logout
11 | Player is ready!
12 | Something went wrong!
13 | Spotify URI to play
14 | Play
15 | Resume
16 | Pause
17 | Resumed!
18 | Paused!
19 | Previous
20 | Next
21 | Skipped to next!
22 | Skipped to previous!
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_descriptor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:7.0.4'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | mavenCentral()
16 | }
17 | }
18 |
19 | task clean(type: Delete) {
20 | delete rootProject.buildDir
21 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | org.gradle.jvmargs=-Xmx1536M --add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'maven-publish'
4 | }
5 |
6 | android {
7 | compileSdkVersion 31
8 | buildToolsVersion "30.0.3"
9 |
10 | defaultConfig {
11 | minSdkVersion 23
12 | targetSdkVersion 31
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | consumerProguardFiles "consumer-rules.pro"
18 |
19 | // TODO use modern way to build native library
20 | sourceSets.main {
21 | jniLibs.srcDir 'src/main/libs'
22 | jni.srcDirs = [] //disable automatic ndk-build call
23 | }
24 |
25 | // call regular ndk-build(.cmd) script from app directory
26 | task ndkBuild(type: Exec) {
27 | commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
28 | }
29 |
30 | tasks.withType(JavaCompile) {
31 | // compileTask -> compileTask.dependsOn ndkBuild
32 | }
33 | }
34 |
35 | buildTypes {
36 | release {
37 | minifyEnabled false
38 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
39 | }
40 | }
41 |
42 | compileOptions {
43 | sourceCompatibility JavaVersion.VERSION_1_8
44 | targetCompatibility JavaVersion.VERSION_1_8
45 | }
46 | }
47 |
48 | dependencies {
49 | implementation 'xyz.gianlu.librespot:librespot-decoder-api:1.6.2'
50 | }
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -keepclassmembers class xyz.gianlu.librespot.player.decoders.tremolo.OggDecodingInputStream {
2 | *;
3 | }
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/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 |
23 | -keepclassmembers class xyz.gianlu.librespot.player.decoders.tremolo.OggDecodingInputStream {
24 | *;
25 | }
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/.gitignore:
--------------------------------------------------------------------------------
1 | obj
2 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/java/xyz/gianlu/librespot/player/decoders/TremoloVorbisDecoder.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.player.decoders;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.io.IOException;
6 | import java.io.OutputStream;
7 |
8 | import xyz.gianlu.librespot.player.decoders.tremolo.OggDecodingInputStream;
9 | import xyz.gianlu.librespot.player.decoders.tremolo.SeekableInputStream;
10 | import xyz.gianlu.librespot.player.mixing.output.OutputAudioFormat;
11 |
12 |
13 | public final class TremoloVorbisDecoder extends Decoder {
14 | private final byte[] buffer = new byte[2 * BUFFER_SIZE];
15 | private final OggDecodingInputStream in;
16 |
17 | public TremoloVorbisDecoder(@NotNull xyz.gianlu.librespot.player.decoders.SeekableInputStream audioFile, float normalizationFactor, int duration) throws IOException {
18 | super(audioFile, normalizationFactor, duration);
19 | seekZero = audioIn.position();
20 | in = new OggDecodingInputStream(new SeekableInputStream() {
21 | @Override
22 | public void seek(long positionBytes) throws IOException {
23 | audioIn.seek((int) (positionBytes + seekZero));
24 | }
25 |
26 | @Override
27 | public long tell() {
28 | return audioIn.position() - seekZero;
29 | }
30 |
31 | @Override
32 | public long length() throws IOException {
33 | return (audioIn.available() + audioIn.position()) - seekZero;
34 | }
35 |
36 | @Override
37 | public int read(byte[] bytes) throws IOException {
38 | return audioIn.read(bytes);
39 | }
40 |
41 | @Override
42 | public void close() {
43 | audioIn.close();
44 | }
45 |
46 | @Override
47 | public int read() throws IOException {
48 | return audioIn.read();
49 | }
50 | });
51 |
52 | setAudioFormat(new OutputAudioFormat(44100, 16, 2, true, false));
53 | }
54 |
55 | @Override
56 | protected synchronized int readInternal(@NotNull OutputStream outputStream) throws IOException {
57 | if (closed) return -1;
58 |
59 | int count = in.read(buffer);
60 | if (count == -1)
61 | return -1;
62 |
63 | outputStream.write(buffer, 0, count);
64 | outputStream.flush();
65 | return count;
66 | }
67 |
68 | @Override
69 | public int time() throws CannotGetTimeException {
70 | if (closed)
71 | throw new CannotGetTimeException("Codec is closed");
72 |
73 | return (int) in.tellMs();
74 | }
75 |
76 | @Override
77 | public void close() throws IOException {
78 | if (in != null) in.close();
79 | super.close();
80 | }
81 |
82 | @Override
83 | public void seek(int positionMs) {
84 | if (!closed) in.seekMs(positionMs);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/java/xyz/gianlu/librespot/player/decoders/tremolo/OggDecodingInputStream.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.player.decoders.tremolo;
2 |
3 | import android.util.Log;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.nio.ByteBuffer;
10 |
11 | /**
12 | * Created by M. Lehmann on 15.11.2016.
13 | */
14 | @SuppressWarnings("unused")
15 | public class OggDecodingInputStream extends InputStream {
16 | private static final int BUFFER_SIZE = 4096;
17 | private static final int SEEK_SET = 0;
18 | private static final int SEEK_CUR = 1;
19 | private static final int SEEK_END = 2;
20 | private final static String TAG = OggDecodingInputStream.class.getName();
21 |
22 | static {
23 | System.loadLibrary("tremolo");
24 | }
25 |
26 | /**
27 | * address of native OggFileHandle structure
28 | **/
29 | private final long handle;
30 | private final SeekableInputStream oggInputStream;
31 | private final ByteBuffer jniBuffer;
32 |
33 | public OggDecodingInputStream(@NotNull SeekableInputStream oggInputStream) throws IOException {
34 | this.oggInputStream = oggInputStream;
35 | this.jniBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
36 | this.handle = initDecoder(jniBuffer);
37 | if (handle == 0)
38 | throw new IOException("Couldn't start decoder!");
39 | }
40 |
41 | private native long initDecoder(ByteBuffer jniBuffer);
42 |
43 | private native int read(long handle, int len);
44 |
45 | private native int seekMs(long handle, int milliseconds);
46 |
47 | private native int seekSamples(long handle, int samples);
48 |
49 | private native long tellMs(long handle);
50 |
51 | private native long tellSamples(long handle);
52 |
53 | private native long totalSamples(long handle);
54 |
55 | private native void close(long handle);
56 |
57 | private int writeOgg(int size) {
58 | byte[] bytes = new byte[Math.min(size, BUFFER_SIZE)];
59 | try {
60 | int read = oggInputStream.read(bytes);
61 | if (read > -1) {
62 | jniBuffer.put(bytes);
63 | jniBuffer.flip();
64 | return read;
65 | }
66 |
67 | return 0;
68 | } catch (Exception ex) {
69 | Log.e(TAG, "Internal writeOgg failed.", ex);
70 | return -1;
71 | }
72 | }
73 |
74 | private int seekOgg(long offset, int whence) {
75 | try {
76 | if (whence == SEEK_SET)
77 | oggInputStream.seek(offset);
78 | else if (whence == SEEK_CUR)
79 | oggInputStream.seek(oggInputStream.tell() + offset);
80 | else if (whence == SEEK_END)
81 | oggInputStream.seek(oggInputStream.length() + offset);
82 |
83 | return 0;
84 | } catch (Exception ex) {
85 | Log.e(TAG, "Internal seekOgg failed.", ex);
86 | return -1;
87 | }
88 | }
89 |
90 | private int tellOgg() {
91 | try {
92 | return (int) oggInputStream.tell();
93 | } catch (Exception ex) {
94 | Log.e(TAG, "Internal tellOgg failed.", ex);
95 | return -1;
96 | }
97 | }
98 |
99 | @Override
100 | public synchronized int read() {
101 | jniBuffer.clear();
102 |
103 | int size = read(handle, 1);
104 | jniBuffer.limit(size);
105 |
106 | byte b = jniBuffer.get();
107 | jniBuffer.clear();
108 | return b;
109 | }
110 |
111 | @Override
112 | public synchronized int read(byte[] b, int off, int len) {
113 | len = Math.min(len, BUFFER_SIZE);
114 | jniBuffer.clear();
115 | int size = read(handle, len);
116 | if (size > 0) {
117 | jniBuffer.limit(size);
118 | jniBuffer.get(b, off, size);
119 | jniBuffer.clear();
120 | return size;
121 | }
122 |
123 | return -1;
124 | }
125 |
126 | @Override
127 | public synchronized int read(byte[] b) {
128 | return this.read(b, 0, b.length);
129 | }
130 |
131 | public synchronized int seekMs(int milliseconds) {
132 | return seekMs(handle, milliseconds);
133 | }
134 |
135 | public synchronized long tellMs() {
136 | return tellMs(handle);
137 | }
138 |
139 | @Override
140 | public synchronized void close() throws IOException {
141 | close(handle);
142 | oggInputStream.close();
143 | super.close();
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/java/xyz/gianlu/librespot/player/decoders/tremolo/SeekableInputStream.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.player.decoders.tremolo;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 |
6 | /**
7 | * Created by M. Lehmann on 08.12.2016.
8 | */
9 | public abstract class SeekableInputStream extends InputStream {
10 |
11 | abstract public void seek(long positionBytes) throws IOException;
12 |
13 | abstract public long tell() throws IOException;
14 |
15 | abstract public long length() throws IOException;
16 |
17 | abstract public int read(byte[] bytes) throws IOException;
18 |
19 | abstract public void close() throws IOException;
20 | }
21 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | include $(wildcard $(call my-dir)/*/Android.mk)
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_PLATFORM := android-14 # proven to work
2 | # TODO: libtremolo _might_ work on x86-devices, you might test it.#
3 | # Otherwise you have to either exclude others or use jorbis for them
4 | APP_ABI := armeabi-v7a arm64-v8a
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 | include $(CLEAR_VARS)
3 |
4 | LOCAL_MODULE := tremolo
5 |
6 | LOCAL_SRC_FILES := bitwise.c \
7 | codebook.c \
8 | dsp.c \
9 | floor0.c \
10 | floor1.c \
11 | floor_lookup.c \
12 | framing.c \
13 | mapping0.c \
14 | mdct.c \
15 | misc.c \
16 | res012.c \
17 | treminfo.c \
18 | vorbisfile.c \
19 | hide.c \
20 | tremolo-jni.c \
21 | md5.c
22 |
23 | ifeq ($(TARGET_ARCH),arm)
24 | LOCAL_ARM_MODE := arm
25 | LOCAL_SRC_FILES += bitwiseARM.s \
26 | dpen.s \
27 | floor1ARM.s \
28 | mdctARM.s
29 | endif
30 |
31 | LOCAL_LDFLAGS += -Wl,--gc-sections
32 |
33 | LOCAL_CFLAGS := -ffast-math -O3 -fvisibility=hidden -ffunction-sections -fdata-sections
34 |
35 | ifeq ($(TARGET_ARCH),arm)
36 | LOCAL_CFLAGS += -D_ARM_ASSEM_
37 | else
38 | LOCAL_CFLAGS += -DONLY_C
39 | endif
40 |
41 | LOCAL_C_INCLUDES:= $(LOCAL_PATH)
42 |
43 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/asm_arm.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: arm7 and later wide math functions
35 |
36 | ************************************************************************/
37 |
38 | #ifdef _ARM_ASSEM_
39 |
40 | #if !defined(_V_WIDE_MATH) && !defined(_LOW_ACCURACY_)
41 | #define _V_WIDE_MATH
42 |
43 | static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) {
44 | int lo,hi;
45 | asm volatile("smull\t%0, %1, %2, %3"
46 | : "=&r"(lo),"=&r"(hi)
47 | : "%r"(x),"r"(y)
48 | : "cc");
49 | return(hi);
50 | }
51 |
52 | static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) {
53 | return MULT32(x,y)<<1;
54 | }
55 |
56 | static inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) {
57 | int lo,hi;
58 | asm volatile("smull %0, %1, %2, %3\n\t"
59 | "movs %0, %0, lsr #15\n\t"
60 | "adc %1, %0, %1, lsl #17\n\t"
61 | : "=&r"(lo),"=&r"(hi)
62 | : "%r"(x),"r"(y)
63 | : "cc");
64 | return(hi);
65 | }
66 |
67 | #define MB() asm volatile ("" : : : "memory")
68 |
69 | static inline void XPROD32(ogg_int32_t a, ogg_int32_t b,
70 | ogg_int32_t t, ogg_int32_t v,
71 | ogg_int32_t *x, ogg_int32_t *y)
72 | {
73 | int x1, y1, l;
74 | asm( "smull %0, %1, %4, %6\n\t"
75 | "smlal %0, %1, %5, %7\n\t"
76 | "rsb %3, %4, #0\n\t"
77 | "smull %0, %2, %5, %6\n\t"
78 | "smlal %0, %2, %3, %7"
79 | : "=&r" (l), "=&r" (x1), "=&r" (y1), "=r" (a)
80 | : "3" (a), "r" (b), "r" (t), "r" (v)
81 | : "cc" );
82 | *x = x1;
83 | MB();
84 | *y = y1;
85 | }
86 |
87 | /* x = (a*t + b*v)>>31, y = (b*t - a*v)>>31 */
88 | static inline void XPROD31(ogg_int32_t a, ogg_int32_t b,
89 | ogg_int32_t t, ogg_int32_t v,
90 | ogg_int32_t *x, ogg_int32_t *y)
91 | {
92 | int x1, y1, l;
93 | asm( "smull %0, %1, %4, %6\n\t"
94 | "smlal %0, %1, %5, %7\n\t"
95 | "rsb %3, %4, #0\n\t"
96 | "smull %0, %2, %5, %6\n\t"
97 | "smlal %0, %2, %3, %7"
98 | : "=&r" (l), "=&r" (x1), "=&r" (y1), "=r" (a)
99 | : "3" (a), "r" (b), "r" (t), "r" (v)
100 | : "cc" );
101 | *x = x1 << 1;
102 | MB();
103 | *y = y1 << 1;
104 | }
105 |
106 | /* x = (a*t - b*v)>>31, y = (b*t + a*v)>>31 */
107 | static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b,
108 | ogg_int32_t t, ogg_int32_t v,
109 | ogg_int32_t *x, ogg_int32_t *y)
110 | {
111 | int x1, y1, l;
112 | asm( "rsb %2, %4, #0\n\t"
113 | "smull %0, %1, %3, %5\n\t"
114 | "smlal %0, %1, %2, %6\n\t"
115 | "smull %0, %2, %4, %5\n\t"
116 | "smlal %0, %2, %3, %6"
117 | : "=&r" (l), "=&r" (x1), "=&r" (y1)
118 | : "r" (a), "r" (b), "r" (t), "r" (v)
119 | : "cc" );
120 | *x = x1 << 1;
121 | MB();
122 | *y = y1 << 1;
123 | }
124 |
125 | #endif
126 |
127 | #ifndef _V_CLIP_MATH
128 | #define _V_CLIP_MATH
129 |
130 | static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
131 | int tmp;
132 | asm volatile("subs %1, %0, #32768\n\t"
133 | "movpl %0, #0x7f00\n\t"
134 | "orrpl %0, %0, #0xff\n"
135 | "adds %1, %0, #32768\n\t"
136 | "movmi %0, #0x8000"
137 | : "+r"(x),"=r"(tmp)
138 | :
139 | : "cc");
140 | return(x);
141 | }
142 |
143 | #endif
144 |
145 | #ifndef _V_LSP_MATH_ASM
146 | #define _V_LSP_MATH_ASM
147 |
148 | static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip,
149 | ogg_int32_t *qexpp,
150 | ogg_int32_t *ilsp,ogg_int32_t wi,
151 | ogg_int32_t m){
152 |
153 | ogg_uint32_t qi=*qip,pi=*pip;
154 | ogg_int32_t qexp=*qexpp;
155 |
156 | asm("mov r0,%3;"
157 | "mov r1,%5,asr#1;"
158 | "add r0,r0,r1,lsl#3;"
159 | "1:"
160 |
161 | "ldmdb r0!,{r1,r3};"
162 | "subs r1,r1,%4;" //ilsp[j]-wi
163 | "rsbmi r1,r1,#0;" //labs(ilsp[j]-wi)
164 | "umull %0,r2,r1,%0;" //qi*=labs(ilsp[j]-wi)
165 |
166 | "subs r1,r3,%4;" //ilsp[j+1]-wi
167 | "rsbmi r1,r1,#0;" //labs(ilsp[j+1]-wi)
168 | "umull %1,r3,r1,%1;" //pi*=labs(ilsp[j+1]-wi)
169 |
170 | "cmn r2,r3;" // shift down 16?
171 | "beq 0f;"
172 | "add %2,%2,#16;"
173 | "mov %0,%0,lsr #16;"
174 | "orr %0,%0,r2,lsl #16;"
175 | "mov %1,%1,lsr #16;"
176 | "orr %1,%1,r3,lsl #16;"
177 | "0:"
178 | "cmp r0,%3;\n"
179 | "bhi 1b;\n"
180 |
181 | // odd filter assymetry
182 | "ands r0,%5,#1;\n"
183 | "beq 2f;\n"
184 | "add r0,%3,%5,lsl#2;\n"
185 |
186 | "ldr r1,[r0,#-4];\n"
187 | "mov r0,#0x4000;\n"
188 |
189 | "subs r1,r1,%4;\n" //ilsp[j]-wi
190 | "rsbmi r1,r1,#0;\n" //labs(ilsp[j]-wi)
191 | "umull %0,r2,r1,%0;\n" //qi*=labs(ilsp[j]-wi)
192 | "umull %1,r3,r0,%1;\n" //pi*=labs(ilsp[j+1]-wi)
193 |
194 | "cmn r2,r3;\n" // shift down 16?
195 | "beq 2f;\n"
196 | "add %2,%2,#16;\n"
197 | "mov %0,%0,lsr #16;\n"
198 | "orr %0,%0,r2,lsl #16;\n"
199 | "mov %1,%1,lsr #16;\n"
200 | "orr %1,%1,r3,lsl #16;\n"
201 |
202 | //qi=(pi>>shift)*labs(ilsp[j]-wi);
203 | //pi=(qi>>shift)*labs(ilsp[j+1]-wi);
204 | //qexp+=shift;
205 |
206 | //}
207 |
208 | /* normalize to max 16 sig figs */
209 | "2:"
210 | "mov r2,#0;"
211 | "orr r1,%0,%1;"
212 | "tst r1,#0xff000000;"
213 | "addne r2,r2,#8;"
214 | "movne r1,r1,lsr #8;"
215 | "tst r1,#0x00f00000;"
216 | "addne r2,r2,#4;"
217 | "movne r1,r1,lsr #4;"
218 | "tst r1,#0x000c0000;"
219 | "addne r2,r2,#2;"
220 | "movne r1,r1,lsr #2;"
221 | "tst r1,#0x00020000;"
222 | "addne r2,r2,#1;"
223 | "movne r1,r1,lsr #1;"
224 | "tst r1,#0x00010000;"
225 | "addne r2,r2,#1;"
226 | "mov %0,%0,lsr r2;"
227 | "mov %1,%1,lsr r2;"
228 | "add %2,%2,r2;"
229 |
230 | : "+r"(qi),"+r"(pi),"+r"(qexp)
231 | : "r"(ilsp),"r"(wi),"r"(m)
232 | : "r0","r1","r2","r3","cc");
233 |
234 | *qip=qi;
235 | *pip=pi;
236 | *qexpp=qexp;
237 | }
238 |
239 | static inline void lsp_norm_asm(ogg_uint32_t *qip,ogg_int32_t *qexpp){
240 |
241 | ogg_uint32_t qi=*qip;
242 | ogg_int32_t qexp=*qexpp;
243 |
244 | asm("tst %0,#0x0000ff00;"
245 | "moveq %0,%0,lsl #8;"
246 | "subeq %1,%1,#8;"
247 | "tst %0,#0x0000f000;"
248 | "moveq %0,%0,lsl #4;"
249 | "subeq %1,%1,#4;"
250 | "tst %0,#0x0000c000;"
251 | "moveq %0,%0,lsl #2;"
252 | "subeq %1,%1,#2;"
253 | "tst %0,#0x00008000;"
254 | "moveq %0,%0,lsl #1;"
255 | "subeq %1,%1,#1;"
256 | : "+r"(qi),"+r"(qexp)
257 | :
258 | : "cc");
259 | *qip=qi;
260 | *qexpp=qexp;
261 | }
262 |
263 | #endif
264 | #endif
265 |
266 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/codebook.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: basic shared codebook operations
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _V_CODEBOOK_H_
39 | #define _V_CODEBOOK_H_
40 |
41 | #include "ogg.h"
42 |
43 | typedef struct codebook{
44 | /* Top 15 used in ARM code */
45 | int dec_maxlength;
46 | void *dec_table;
47 | int dec_method;
48 | int dec_type; /* 0 = entry number
49 | 1 = packed vector of values
50 | 2 = packed vector of column offsets, maptype 1
51 | 3 = scalar offset into value array, maptype 2 */
52 | int q_bits;
53 | long dim; /* codebook dimensions (elements per vector) */
54 | int q_delp;
55 | int q_minp;
56 | ogg_int32_t q_del;
57 | ogg_int32_t q_min;
58 | int q_seq;
59 | int q_pack;
60 | void *q_val;
61 | long used_entries; /* populated codebook entries */
62 | ogg_int32_t *dec_buf;
63 |
64 | /* C only */
65 | int dec_nodeb;
66 | int dec_leafw;
67 |
68 | long entries; /* codebook entries */
69 |
70 | } codebook;
71 |
72 | extern void vorbis_book_clear(codebook *b);
73 | extern int vorbis_book_unpack(oggpack_buffer *b,codebook *c);
74 |
75 | extern long vorbis_book_decode(codebook *book, oggpack_buffer *b);
76 | extern long vorbis_book_decodevs_add(codebook *book, ogg_int32_t *a,
77 | oggpack_buffer *b,int n,int point);
78 | extern long vorbis_book_decodev_set(codebook *book, ogg_int32_t *a,
79 | oggpack_buffer *b,int n,int point);
80 | extern long vorbis_book_decodev_add(codebook *book, ogg_int32_t *a,
81 | oggpack_buffer *b,int n,int point);
82 | extern long vorbis_book_decodevv_add(codebook *book, ogg_int32_t **a,
83 | long off,int ch,
84 | oggpack_buffer *b,int n,int point);
85 |
86 | extern int _ilog(unsigned int v);
87 |
88 |
89 | #endif
90 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/codec_internal.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: libvorbis codec headers
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _V_CODECI_H_
39 | #define _V_CODECI_H_
40 |
41 | #define CHUNKSIZE 1024
42 |
43 | #include "codebook.h"
44 | #include "ivorbiscodec.h"
45 |
46 | #define VI_TRANSFORMB 1
47 | #define VI_WINDOWB 1
48 | #define VI_TIMEB 1
49 | #define VI_FLOORB 2
50 | #define VI_RESB 3
51 | #define VI_MAPB 1
52 |
53 | typedef void vorbis_info_floor;
54 |
55 | /* vorbis_dsp_state buffers the current vorbis audio
56 | analysis/synthesis state. The DSP state belongs to a specific
57 | logical bitstream ****************************************************/
58 | struct vorbis_dsp_state{
59 | vorbis_info *vi;
60 | oggpack_buffer opb;
61 |
62 | ogg_int32_t **work;
63 | ogg_int32_t **mdctright;
64 | int out_begin;
65 | int out_end;
66 |
67 | long lW;
68 | long W;
69 |
70 | ogg_int64_t granulepos;
71 | ogg_int64_t sequence;
72 | ogg_int64_t sample_count;
73 |
74 | };
75 |
76 |
77 | /* Floor backend generic *****************************************/
78 |
79 | extern vorbis_info_floor *floor0_info_unpack(vorbis_info *,oggpack_buffer *);
80 | extern void floor0_free_info(vorbis_info_floor *);
81 | extern int floor0_memosize(vorbis_info_floor *);
82 | extern ogg_int32_t *floor0_inverse1(struct vorbis_dsp_state *,
83 | vorbis_info_floor *,ogg_int32_t *);
84 | extern int floor0_inverse2 (struct vorbis_dsp_state *,vorbis_info_floor *,
85 | ogg_int32_t *buffer,ogg_int32_t *);
86 |
87 | extern vorbis_info_floor *floor1_info_unpack(vorbis_info *,oggpack_buffer *);
88 | extern void floor1_free_info(vorbis_info_floor *);
89 | extern int floor1_memosize(vorbis_info_floor *);
90 | extern ogg_int32_t *floor1_inverse1(struct vorbis_dsp_state *,
91 | vorbis_info_floor *,ogg_int32_t *);
92 | extern int floor1_inverse2 (struct vorbis_dsp_state *,vorbis_info_floor *,
93 | ogg_int32_t *buffer,ogg_int32_t *);
94 |
95 | typedef struct{
96 | int order;
97 | long rate;
98 | long barkmap;
99 |
100 | int ampbits;
101 | int ampdB;
102 |
103 | int numbooks; /* <= 16 */
104 | char books[16];
105 |
106 | } vorbis_info_floor0;
107 |
108 | typedef struct{
109 | char class_dim; /* 1 to 8 */
110 | char class_subs; /* 0,1,2,3 (bits: 1<
39 | #include "ogg.h"
40 | #include "mdct.h"
41 | #include "ivorbiscodec.h"
42 | #include "codec_internal.h"
43 | #include "misc.h"
44 | #include "window_lookup.h"
45 |
46 | int vorbis_dsp_restart(vorbis_dsp_state *v){
47 | if(!v)return -1;
48 | {
49 | vorbis_info *vi=v->vi;
50 | codec_setup_info *ci;
51 |
52 | if(!vi)return -1;
53 | ci=vi->codec_setup;
54 | if(!ci)return -1;
55 |
56 | v->out_end=-1;
57 | v->out_begin=-1;
58 |
59 | v->granulepos=-1;
60 | v->sequence=-1;
61 | v->sample_count=-1;
62 | }
63 | return 0;
64 | }
65 |
66 | int vorbis_dsp_init(vorbis_dsp_state *v,vorbis_info *vi){
67 | int i;
68 |
69 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
70 |
71 | v->vi=vi;
72 |
73 | v->work=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->work));
74 | v->mdctright=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->mdctright));
75 | for(i=0;ichannels;i++){
76 | v->work[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>1)*
77 | sizeof(*v->work[i]));
78 | v->mdctright[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>2)*
79 | sizeof(*v->mdctright[i]));
80 | }
81 |
82 | v->lW=0; /* previous window size */
83 | v->W=0; /* current window size */
84 |
85 | vorbis_dsp_restart(v);
86 | return 0;
87 | }
88 |
89 | vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){
90 | vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v));
91 | vorbis_dsp_init(v,vi);
92 | return v;
93 | }
94 |
95 | void vorbis_dsp_clear(vorbis_dsp_state *v){
96 | int i;
97 | if(v){
98 | vorbis_info *vi=v->vi;
99 |
100 | if(v->work){
101 | for(i=0;ichannels;i++)
102 | if(v->work[i])_ogg_free(v->work[i]);
103 | _ogg_free(v->work);
104 | }
105 | if(v->mdctright){
106 | for(i=0;ichannels;i++)
107 | if(v->mdctright[i])_ogg_free(v->mdctright[i]);
108 | _ogg_free(v->mdctright);
109 | }
110 | }
111 | }
112 |
113 | void vorbis_dsp_destroy(vorbis_dsp_state *v){
114 | vorbis_dsp_clear(v);
115 | _ogg_free(v);
116 | }
117 |
118 | static LOOKUP_T *_vorbis_window(int left){
119 | switch(left){
120 | case 32:
121 | return vwin64;
122 | case 64:
123 | return vwin128;
124 | case 128:
125 | return vwin256;
126 | case 256:
127 | return vwin512;
128 | case 512:
129 | return vwin1024;
130 | case 1024:
131 | return vwin2048;
132 | case 2048:
133 | return vwin4096;
134 | #ifndef LIMIT_TO_64kHz
135 | case 4096:
136 | return vwin8192;
137 | #endif
138 | default:
139 | return(0);
140 | }
141 | }
142 |
143 | /* pcm==0 indicates we just want the pending samples, no more */
144 | int vorbis_dsp_pcmout(vorbis_dsp_state *v,ogg_int16_t *pcm,int samples){
145 | vorbis_info *vi=v->vi;
146 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
147 | if(v->out_begin>-1 && v->out_beginout_end){
148 | int n=v->out_end-v->out_begin;
149 | if(pcm){
150 | int i;
151 | if(n>samples)n=samples;
152 | for(i=0;ichannels;i++)
153 | mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1],
154 | v->lW,v->W,v->work[i],v->mdctright[i],
155 | _vorbis_window(ci->blocksizes[0]>>1),
156 | _vorbis_window(ci->blocksizes[1]>>1),
157 | pcm+i,vi->channels,
158 | v->out_begin,v->out_begin+n);
159 | }
160 | return(n);
161 | }
162 | return(0);
163 | }
164 |
165 | int vorbis_dsp_read(vorbis_dsp_state *v,int s){
166 | if(s && v->out_begin+s>v->out_end)return(OV_EINVAL);
167 | v->out_begin+=s;
168 | return(0);
169 | }
170 |
171 | long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
172 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
173 | oggpack_buffer opb;
174 | int mode;
175 | int modebits=0;
176 | int v=ci->modes;
177 |
178 | oggpack_readinit(&opb,op->packet);
179 |
180 | /* Check the packet type */
181 | if(oggpack_read(&opb,1)!=0){
182 | /* Oops. This is not an audio data packet */
183 | return(OV_ENOTAUDIO);
184 | }
185 |
186 | while(v>1){
187 | modebits++;
188 | v>>=1;
189 | }
190 |
191 | /* read our mode and pre/post windowsize */
192 | mode=oggpack_read(&opb,modebits);
193 | if(mode==-1)return(OV_EBADPACKET);
194 | return(ci->blocksizes[ci->mode_param[mode].blockflag]);
195 | }
196 |
197 |
198 | static int ilog(ogg_uint32_t v){
199 | int ret=0;
200 | if(v)--v;
201 | while(v){
202 | ret++;
203 | v>>=1;
204 | }
205 | return(ret);
206 | }
207 |
208 | int vorbis_dsp_synthesis(vorbis_dsp_state *vd,ogg_packet *op,int decodep){
209 | vorbis_info *vi=vd->vi;
210 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
211 | int mode,i;
212 |
213 | oggpack_readinit(&vd->opb,op->packet);
214 |
215 | /* Check the packet type */
216 | if(oggpack_read(&vd->opb,1)!=0){
217 | /* Oops. This is not an audio data packet */
218 | return OV_ENOTAUDIO ;
219 | }
220 |
221 | /* read our mode and pre/post windowsize */
222 | mode=oggpack_read(&vd->opb,ilog(ci->modes));
223 | if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET;
224 |
225 | /* shift information we still need from last window */
226 | vd->lW=vd->W;
227 | vd->W=ci->mode_param[mode].blockflag;
228 | for(i=0;ichannels;i++)
229 | mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]);
230 |
231 | if(vd->W){
232 | int temp;
233 | oggpack_read(&vd->opb,1);
234 | temp=oggpack_read(&vd->opb,1);
235 | if(temp==-1) return OV_EBADPACKET;
236 | }
237 |
238 | /* packet decode and portions of synthesis that rely on only this block */
239 | if(decodep){
240 | mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping);
241 |
242 | if(vd->out_begin==-1){
243 | vd->out_begin=0;
244 | vd->out_end=0;
245 | }else{
246 | vd->out_begin=0;
247 | vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
248 | }
249 | }
250 |
251 | /* track the frame number... This is for convenience, but also
252 | making sure our last packet doesn't end with added padding.
253 |
254 | This is not foolproof! It will be confused if we begin
255 | decoding at the last page after a seek or hole. In that case,
256 | we don't have a starting point to judge where the last frame
257 | is. For this reason, vorbisfile will always try to make sure
258 | it reads the last two marked pages in proper sequence */
259 |
260 | /* if we're out of sequence, dump granpos tracking until we sync back up */
261 | if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){
262 | /* out of sequence; lose count */
263 | vd->granulepos=-1;
264 | vd->sample_count=-1;
265 | }
266 |
267 | vd->sequence=op->packetno;
268 | vd->sequence=vd->sequence-3;
269 |
270 | if(vd->sample_count==-1){
271 | vd->sample_count=0;
272 | }else{
273 | vd->sample_count+=
274 | ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
275 | }
276 |
277 | if(vd->granulepos==-1){
278 | if(op->granulepos!=-1){ /* only set if we have a
279 | position to set to */
280 |
281 | vd->granulepos=op->granulepos;
282 |
283 | /* is this a short page? */
284 | if(vd->sample_count>vd->granulepos){
285 | /* corner case; if this is both the first and last audio page,
286 | then spec says the end is cut, not beginning */
287 | if(op->e_o_s){
288 | /* trim the end */
289 | /* no preceeding granulepos; assume we started at zero (we'd
290 | have to in a short single-page stream) */
291 | /* granulepos could be -1 due to a seek, but that would result
292 | in a long coun t, not short count */
293 |
294 | vd->out_end-=(int)(vd->sample_count-vd->granulepos);
295 | }else{
296 | /* trim the beginning */
297 | vd->out_begin+=(int)(vd->sample_count-vd->granulepos);
298 | if(vd->out_begin>vd->out_end)
299 | vd->out_begin=vd->out_end;
300 | }
301 |
302 | }
303 |
304 | }
305 | }else{
306 | vd->granulepos+=
307 | ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
308 | if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){
309 |
310 | if(vd->granulepos>op->granulepos){
311 | long extra=(long)(vd->granulepos-op->granulepos);
312 |
313 | if(extra)
314 | if(op->e_o_s){
315 | /* partial last frame. Strip the extra samples off */
316 | vd->out_end-=extra;
317 | } /* else {Shouldn't happen *unless* the bitstream is out of
318 | spec. Either way, believe the bitstream } */
319 | } /* else {Shouldn't happen *unless* the bitstream is out of
320 | spec. Either way, believe the bitstream } */
321 | vd->granulepos=op->granulepos;
322 | }
323 | }
324 |
325 | return(0);
326 | }
327 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/floor1ARM.s:
--------------------------------------------------------------------------------
1 | @ Tremolo library
2 | @-----------------------------------------------------------------------
3 | @ Copyright (C) 2002-2009, Xiph.org Foundation
4 | @ Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
5 | @ All rights reserved.
6 |
7 | @ Redistribution and use in source and binary forms, with or without
8 | @ modification, are permitted provided that the following conditions
9 | @ are met:
10 |
11 | @ * Redistributions of source code must retain the above copyright
12 | @ notice, this list of conditions and the following disclaimer.
13 | @ * Redistributions in binary form must reproduce the above
14 | @ copyright notice, this list of conditions and the following disclaimer
15 | @ in the documentation and/or other materials provided with the
16 | @ distribution.
17 | @ * Neither the names of the Xiph.org Foundation nor Pinknoise
18 | @ Productions Ltd nor the names of its contributors may be used to
19 | @ endorse or promote products derived from this software without
20 | @ specific prior written permission.
21 | @
22 | @ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 | @ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 | @ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 | @ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 | @ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 | @ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 | @ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 | @ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 | @ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 | @ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 | @ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 | @ ----------------------------------------------------------------------
34 |
35 | .text
36 |
37 | .global render_lineARM
38 |
39 | render_lineARM:
40 | @ r0 = n
41 | @ r1 = d
42 | @ r2 = floor
43 | @ r3 = base
44 | @ <> = err
45 | @ <> = adx
46 | @ <> = ady
47 | MOV r12,r13
48 | STMFD r13!,{r4-r6,r11,r14}
49 | LDMFD r12,{r11,r12,r14} @ r11 = err
50 | @ r12 = adx
51 | @ r14 = ady
52 | rl_loop:
53 | LDR r4,[r1] @ r4 = *d
54 | LDR r5,[r2],r3,LSL #2 @ r5 = *floor r2 = floor+base
55 | SUBS r11,r11,r14 @ err -= ady
56 | ADDLT r11,r11,r12 @ if (err < 0) err+=adx
57 | SMULL r6, r5, r4, r5 @ (r6,r5) = *d * *floor
58 | ADDLT r2, r2, #4 @ floor+=1
59 | MOVS r6, r6, LSR #15
60 | ADC r5, r6, r5, LSL #17 @ r5 = MULT31_SHIFT15
61 | STR r5,[r1],#4
62 | SUBS r0, r0, #1
63 | BGT rl_loop
64 |
65 | LDMFD r13!,{r4-r6,r11,PC}
66 |
67 | @ END
68 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/floor_lookup.c:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: floor dB lookup
35 |
36 | ************************************************************************/
37 |
38 | #include "os.h"
39 |
40 | #ifdef _LOW_ACCURACY_
41 | # define XdB(n) ((((n)>>8)+1)>>1)
42 | #else
43 | # define XdB(n) (n)
44 | #endif
45 |
46 | const ogg_int32_t FLOOR_fromdB_LOOKUP[256]={
47 | XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114),
48 | XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163),
49 | XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9),
50 | XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c),
51 | XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4),
52 | XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd),
53 | XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4),
54 | XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a),
55 | XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818),
56 | XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69),
57 | XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64),
58 | XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a),
59 | XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629),
60 | XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82),
61 | XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac),
62 | XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c),
63 | XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf),
64 | XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10),
65 | XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b),
66 | XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e),
67 | XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d),
68 | XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4),
69 | XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd),
70 | XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf),
71 | XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e),
72 | XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962),
73 | XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109),
74 | XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4),
75 | XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23),
76 | XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306),
77 | XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20),
78 | XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6),
79 | XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471),
80 | XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1),
81 | XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7),
82 | XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d),
83 | XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1),
84 | XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc),
85 | XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2),
86 | XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488),
87 | XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0),
88 | XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f),
89 | XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41),
90 | XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17),
91 | XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e),
92 | XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7),
93 | XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf),
94 | XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea),
95 | XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793),
96 | XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2),
97 | XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013),
98 | XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204),
99 | XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299),
100 | XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e),
101 | XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca),
102 | XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea),
103 | XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1),
104 | XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1),
105 | XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870),
106 | XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6),
107 | XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44),
108 | XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e),
109 | XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298),
110 | XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff),
111 | };
112 |
113 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/hide.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/librespot-android-decoder-tremolo/src/main/jni/libtremolo/hide.c
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/hide.h:
--------------------------------------------------------------------------------
1 | #ifndef LIB_DECODE__H
2 | #define LIB_DECODE__H
3 |
4 | char *decode(const char *str);
5 | char *encode(const char *str);
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/ivorbiscodec.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: libvorbis codec headers
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _vorbis_codec_h_
39 | #define _vorbis_codec_h_
40 |
41 | #ifdef __cplusplus
42 | extern "C"
43 | {
44 | #endif /* __cplusplus */
45 |
46 | #include "ogg.h"
47 |
48 | struct vorbis_dsp_state;
49 | typedef struct vorbis_dsp_state vorbis_dsp_state;
50 |
51 | typedef struct vorbis_info{
52 | int version;
53 | int channels;
54 | long rate;
55 |
56 | /* The below bitrate declarations are *hints*.
57 | Combinations of the three values carry the following implications:
58 |
59 | all three set to the same value:
60 | implies a fixed rate bitstream
61 | only nominal set:
62 | implies a VBR stream that averages the nominal bitrate. No hard
63 | upper/lower limit
64 | upper and or lower set:
65 | implies a VBR bitstream that obeys the bitrate limits. nominal
66 | may also be set to give a nominal rate.
67 | none set:
68 | the coder does not care to speculate.
69 | */
70 |
71 | long bitrate_upper;
72 | long bitrate_nominal;
73 | long bitrate_lower;
74 | long bitrate_window;
75 |
76 | void *codec_setup;
77 | } vorbis_info;
78 |
79 | typedef struct vorbis_comment{
80 | char **user_comments;
81 | int *comment_lengths;
82 | int comments;
83 | char *vendor;
84 |
85 | } vorbis_comment;
86 |
87 |
88 | /* Vorbis PRIMITIVES: general ***************************************/
89 |
90 | extern void vorbis_info_init(vorbis_info *vi);
91 | extern void vorbis_info_clear(vorbis_info *vi);
92 | extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
93 | extern void vorbis_comment_init(vorbis_comment *vc);
94 | extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
95 | extern void vorbis_comment_add_tag(vorbis_comment *vc,
96 | char *tag, char *contents);
97 | extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
98 | extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
99 | extern void vorbis_comment_clear(vorbis_comment *vc);
100 |
101 | /* Vorbis ERRORS and return codes ***********************************/
102 |
103 | #define OV_FALSE -1
104 | #define OV_EOF -2
105 | #define OV_HOLE -3
106 |
107 | #define OV_EREAD -128
108 | #define OV_EFAULT -129
109 | #define OV_EIMPL -130
110 | #define OV_EINVAL -131
111 | #define OV_ENOTVORBIS -132
112 | #define OV_EBADHEADER -133
113 | #define OV_EVERSION -134
114 | #define OV_ENOTAUDIO -135
115 | #define OV_EBADPACKET -136
116 | #define OV_EBADLINK -137
117 | #define OV_ENOSEEK -138
118 |
119 | #ifdef __cplusplus
120 | }
121 | #endif /* __cplusplus */
122 |
123 | #endif
124 |
125 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/ivorbisfile.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: stdio-based convenience library for opening/seeking/decoding
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _OV_FILE_H_
39 | #define _OV_FILE_H_
40 |
41 | #ifdef __cplusplus
42 | extern "C"
43 | {
44 | #endif /* __cplusplus */
45 |
46 | #include
47 | #include "ivorbiscodec.h"
48 |
49 | /* The function prototypes for the callbacks are basically the same as for
50 | * the stdio functions fread, fseek, fclose, ftell.
51 | * The one difference is that the FILE * arguments have been replaced with
52 | * a void * - this is to be used as a pointer to whatever internal data these
53 | * functions might need. In the stdio case, it's just a FILE * cast to a void *
54 | *
55 | * If you use other functions, check the docs for these functions and return
56 | * the right values. For seek_func(), you *MUST* return -1 if the stream is
57 | * unseekable
58 | */
59 | typedef struct {
60 | size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
61 | int (*seek_func) (void *datasource, ogg_int64_t offset, int whence);
62 | int (*close_func) (void *datasource);
63 | long (*tell_func) (void *datasource);
64 | } ov_callbacks;
65 |
66 | typedef struct OggVorbis_File {
67 | void *datasource; /* Pointer to a FILE *, etc. */
68 | int seekable;
69 | ogg_int64_t offset;
70 | ogg_int64_t end;
71 | ogg_sync_state *oy;
72 |
73 | /* If the FILE handle isn't seekable (eg, a pipe), only the current
74 | stream appears */
75 | int links;
76 | ogg_int64_t *offsets;
77 | ogg_int64_t *dataoffsets;
78 | ogg_uint32_t *serialnos;
79 | ogg_int64_t *pcmlengths;
80 | vorbis_info vi;
81 | vorbis_comment vc;
82 |
83 | /* Decoding working state local storage */
84 | ogg_int64_t pcm_offset;
85 | int ready_state;
86 | ogg_uint32_t current_serialno;
87 | int current_link;
88 |
89 | ogg_int64_t bittrack;
90 | ogg_int64_t samptrack;
91 |
92 | ogg_stream_state *os; /* take physical pages, weld into a logical
93 | stream of packets */
94 | vorbis_dsp_state *vd; /* central working state for the packet->PCM decoder */
95 |
96 | ov_callbacks callbacks;
97 |
98 | } OggVorbis_File;
99 |
100 | extern int ov_clear(OggVorbis_File *vf);
101 | extern int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
102 | extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
103 | char *initial, long ibytes, ov_callbacks callbacks);
104 |
105 | extern int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes);
106 | extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
107 | char *initial, long ibytes, ov_callbacks callbacks);
108 | extern int ov_test_open(OggVorbis_File *vf);
109 |
110 | extern long ov_bitrate(OggVorbis_File *vf,int i);
111 | extern long ov_bitrate_instant(OggVorbis_File *vf);
112 | extern long ov_streams(OggVorbis_File *vf);
113 | extern long ov_seekable(OggVorbis_File *vf);
114 | extern long ov_serialnumber(OggVorbis_File *vf,int i);
115 |
116 | extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i);
117 | extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i);
118 | extern ogg_int64_t ov_time_total(OggVorbis_File *vf,int i);
119 |
120 | extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos);
121 | extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos);
122 | extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos);
123 | extern int ov_time_seek(OggVorbis_File *vf,ogg_int64_t pos);
124 | extern int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t pos);
125 |
126 | extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf);
127 | extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf);
128 | extern ogg_int64_t ov_time_tell(OggVorbis_File *vf);
129 |
130 | extern vorbis_info *ov_info(OggVorbis_File *vf,int link);
131 | extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link);
132 |
133 | extern long ov_read(OggVorbis_File *vf,void *buffer,int length,
134 | int *bitstream);
135 |
136 | #ifdef __cplusplus
137 | }
138 | #endif /* __cplusplus */
139 |
140 | #endif
141 |
142 |
143 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/lsp_lookup.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: lookup data
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _V_LOOKUP_DATA_H_
39 | #define _V_LOOKUP_DATA_H_
40 |
41 | #include "os_types.h"
42 |
43 | #define INVSQ_LOOKUP_I_SHIFT 10
44 | #define INVSQ_LOOKUP_I_MASK 1023
45 | static const long INVSQ_LOOKUP_I[64+1]={
46 | 92682, 91966, 91267, 90583,
47 | 89915, 89261, 88621, 87995,
48 | 87381, 86781, 86192, 85616,
49 | 85051, 84497, 83953, 83420,
50 | 82897, 82384, 81880, 81385,
51 | 80899, 80422, 79953, 79492,
52 | 79039, 78594, 78156, 77726,
53 | 77302, 76885, 76475, 76072,
54 | 75674, 75283, 74898, 74519,
55 | 74146, 73778, 73415, 73058,
56 | 72706, 72359, 72016, 71679,
57 | 71347, 71019, 70695, 70376,
58 | 70061, 69750, 69444, 69141,
59 | 68842, 68548, 68256, 67969,
60 | 67685, 67405, 67128, 66855,
61 | 66585, 66318, 66054, 65794,
62 | 65536,
63 | };
64 |
65 | static const long INVSQ_LOOKUP_IDel[64]={
66 | 716, 699, 684, 668,
67 | 654, 640, 626, 614,
68 | 600, 589, 576, 565,
69 | 554, 544, 533, 523,
70 | 513, 504, 495, 486,
71 | 477, 469, 461, 453,
72 | 445, 438, 430, 424,
73 | 417, 410, 403, 398,
74 | 391, 385, 379, 373,
75 | 368, 363, 357, 352,
76 | 347, 343, 337, 332,
77 | 328, 324, 319, 315,
78 | 311, 306, 303, 299,
79 | 294, 292, 287, 284,
80 | 280, 277, 273, 270,
81 | 267, 264, 260, 258,
82 | };
83 |
84 | #define COS_LOOKUP_I_SHIFT 9
85 | #define COS_LOOKUP_I_MASK 511
86 | #define COS_LOOKUP_I_SZ 128
87 | static const ogg_int32_t COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={
88 | 16384, 16379, 16364, 16340,
89 | 16305, 16261, 16207, 16143,
90 | 16069, 15986, 15893, 15791,
91 | 15679, 15557, 15426, 15286,
92 | 15137, 14978, 14811, 14635,
93 | 14449, 14256, 14053, 13842,
94 | 13623, 13395, 13160, 12916,
95 | 12665, 12406, 12140, 11866,
96 | 11585, 11297, 11003, 10702,
97 | 10394, 10080, 9760, 9434,
98 | 9102, 8765, 8423, 8076,
99 | 7723, 7366, 7005, 6639,
100 | 6270, 5897, 5520, 5139,
101 | 4756, 4370, 3981, 3590,
102 | 3196, 2801, 2404, 2006,
103 | 1606, 1205, 804, 402,
104 | 0, -401, -803, -1204,
105 | -1605, -2005, -2403, -2800,
106 | -3195, -3589, -3980, -4369,
107 | -4755, -5138, -5519, -5896,
108 | -6269, -6638, -7004, -7365,
109 | -7722, -8075, -8422, -8764,
110 | -9101, -9433, -9759, -10079,
111 | -10393, -10701, -11002, -11296,
112 | -11584, -11865, -12139, -12405,
113 | -12664, -12915, -13159, -13394,
114 | -13622, -13841, -14052, -14255,
115 | -14448, -14634, -14810, -14977,
116 | -15136, -15285, -15425, -15556,
117 | -15678, -15790, -15892, -15985,
118 | -16068, -16142, -16206, -16260,
119 | -16304, -16339, -16363, -16378,
120 | -16383,
121 | };
122 |
123 | #endif
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/mapping0.c:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: channel mapping 0 implementation
35 |
36 | ************************************************************************/
37 |
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include "ogg.h"
43 | #include "os.h"
44 | #include "ivorbiscodec.h"
45 | #include "mdct.h"
46 | #include "codec_internal.h"
47 | #include "codebook.h"
48 | #include "misc.h"
49 |
50 | void mapping_clear_info(vorbis_info_mapping *info){
51 | if(info){
52 | if(info->chmuxlist)_ogg_free(info->chmuxlist);
53 | if(info->submaplist)_ogg_free(info->submaplist);
54 | if(info->coupling)_ogg_free(info->coupling);
55 | memset(info,0,sizeof(*info));
56 | }
57 | }
58 |
59 | static int ilog(unsigned int v){
60 | int ret=0;
61 | if(v)--v;
62 | while(v){
63 | ret++;
64 | v>>=1;
65 | }
66 | return(ret);
67 | }
68 |
69 | /* also responsible for range checking */
70 | int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi,
71 | oggpack_buffer *opb){
72 | int i;
73 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
74 | memset(info,0,sizeof(*info));
75 |
76 | if(oggpack_read(opb,1))
77 | info->submaps=oggpack_read(opb,4)+1;
78 | else
79 | info->submaps=1;
80 |
81 | if(oggpack_read(opb,1)){
82 | info->coupling_steps=oggpack_read(opb,8)+1;
83 | info->coupling=
84 | _ogg_malloc(info->coupling_steps*sizeof(*info->coupling));
85 |
86 | for(i=0;icoupling_steps;i++){
87 | int testM=info->coupling[i].mag=(unsigned char)(oggpack_read(opb,ilog(vi->channels)));
88 | int testA=info->coupling[i].ang=(unsigned char)(oggpack_read(opb,ilog(vi->channels)));
89 |
90 | if(testM<0 ||
91 | testA<0 ||
92 | testM==testA ||
93 | testM>=vi->channels ||
94 | testA>=vi->channels) goto err_out;
95 | }
96 |
97 | }
98 |
99 | if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
100 |
101 | if(info->submaps>1){
102 | info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels);
103 | for(i=0;ichannels;i++){
104 | info->chmuxlist[i]=(unsigned char)(oggpack_read(opb,4));
105 | if(info->chmuxlist[i]>=info->submaps)goto err_out;
106 | }
107 | }
108 |
109 | info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps);
110 | for(i=0;isubmaps;i++){
111 | int temp=oggpack_read(opb,8);
112 | info->submaplist[i].floor=(char)oggpack_read(opb,8);
113 | if(info->submaplist[i].floor>=ci->floors)goto err_out;
114 | info->submaplist[i].residue=(char)oggpack_read(opb,8);
115 | if(info->submaplist[i].residue>=ci->residues)goto err_out;
116 | }
117 |
118 | return 0;
119 |
120 | err_out:
121 | mapping_clear_info(info);
122 | return -1;
123 | }
124 |
125 | int mapping_inverse(vorbis_dsp_state *vd,vorbis_info_mapping *info){
126 | vorbis_info *vi=vd->vi;
127 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
128 |
129 | int i,j;
130 | long n=ci->blocksizes[vd->W];
131 |
132 | ogg_int32_t **pcmbundle=
133 | alloca(sizeof(*pcmbundle)*vi->channels);
134 | int *zerobundle=
135 | alloca(sizeof(*zerobundle)*vi->channels);
136 | int *nonzero=
137 | alloca(sizeof(*nonzero)*vi->channels);
138 | ogg_int32_t **floormemo=
139 | alloca(sizeof(*floormemo)*vi->channels);
140 |
141 | /* recover the spectral envelope; store it in the PCM vector for now */
142 | for(i=0;ichannels;i++){
143 | int submap=0;
144 | int floorno;
145 |
146 | if(info->submaps>1)
147 | submap=info->chmuxlist[i];
148 | floorno=info->submaplist[submap].floor;
149 |
150 | if(ci->floor_type[floorno]){
151 | /* floor 1 */
152 | floormemo[i]=alloca(sizeof(*floormemo[i])*
153 | floor1_memosize(ci->floor_param[floorno]));
154 | floormemo[i]=floor1_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
155 | }else{
156 | /* floor 0 */
157 | floormemo[i]=alloca(sizeof(*floormemo[i])*
158 | floor0_memosize(ci->floor_param[floorno]));
159 | floormemo[i]=floor0_inverse1(vd,ci->floor_param[floorno],floormemo[i]);
160 | }
161 |
162 | if(floormemo[i])
163 | nonzero[i]=1;
164 | else
165 | nonzero[i]=0;
166 | memset(vd->work[i],0,sizeof(*vd->work[i])*n/2);
167 | }
168 |
169 | /* channel coupling can 'dirty' the nonzero listing */
170 | for(i=0;icoupling_steps;i++){
171 | if(nonzero[info->coupling[i].mag] ||
172 | nonzero[info->coupling[i].ang]){
173 | nonzero[info->coupling[i].mag]=1;
174 | nonzero[info->coupling[i].ang]=1;
175 | }
176 | }
177 |
178 | /* recover the residue into our working vectors */
179 | for(i=0;isubmaps;i++){
180 | int ch_in_bundle=0;
181 | for(j=0;jchannels;j++){
182 | if(!info->chmuxlist || info->chmuxlist[j]==i){
183 | if(nonzero[j])
184 | zerobundle[ch_in_bundle]=1;
185 | else
186 | zerobundle[ch_in_bundle]=0;
187 | pcmbundle[ch_in_bundle++]=vd->work[j];
188 | }
189 | }
190 |
191 | res_inverse(vd,ci->residue_param+info->submaplist[i].residue,
192 | pcmbundle,zerobundle,ch_in_bundle);
193 | }
194 |
195 | //for(j=0;jchannels;j++)
196 | //_analysis_output("coupled",seq+j,vb->pcm[j],-8,n/2,0,0);
197 |
198 | /* channel coupling */
199 | for(i=info->coupling_steps-1;i>=0;i--){
200 | ogg_int32_t *pcmM=vd->work[info->coupling[i].mag];
201 | ogg_int32_t *pcmA=vd->work[info->coupling[i].ang];
202 |
203 | for(j=0;j0)
208 | if(ang>0){
209 | pcmM[j]=mag;
210 | pcmA[j]=mag-ang;
211 | }else{
212 | pcmA[j]=mag;
213 | pcmM[j]=mag+ang;
214 | }
215 | else
216 | if(ang>0){
217 | pcmM[j]=mag;
218 | pcmA[j]=mag+ang;
219 | }else{
220 | pcmA[j]=mag;
221 | pcmM[j]=mag-ang;
222 | }
223 | }
224 | }
225 |
226 | //for(j=0;jchannels;j++)
227 | //_analysis_output("residue",seq+j,vb->pcm[j],-8,n/2,0,0);
228 |
229 | /* compute and apply spectral envelope */
230 | for(i=0;ichannels;i++){
231 | ogg_int32_t *pcm=vd->work[i];
232 | int submap=0;
233 | int floorno;
234 |
235 | if(info->submaps>1)
236 | submap=info->chmuxlist[i];
237 | floorno=info->submaplist[submap].floor;
238 |
239 | if(ci->floor_type[floorno]){
240 | /* floor 1 */
241 | floor1_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
242 | }else{
243 | /* floor 0 */
244 | floor0_inverse2(vd,ci->floor_param[floorno],floormemo[i],pcm);
245 | }
246 | }
247 |
248 | //for(j=0;jchannels;j++)
249 | //_analysis_output("mdct",seq+j,vb->pcm[j],-24,n/2,0,1);
250 |
251 | /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
252 | /* only MDCT right now.... */
253 | for(i=0;ichannels;i++)
254 | mdct_backward(n,vd->work[i]);
255 |
256 | //for(j=0;jchannels;j++)
257 | //_analysis_output("imdct",seq+j,vb->pcm[j],-24,n,0,0);
258 |
259 | /* all done! */
260 | return(0);
261 | }
262 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/md5.c:
--------------------------------------------------------------------------------
1 | /*
2 | * This code implements the MD5 message-digest algorithm.
3 | * The algorithm is due to Ron Rivest. This code was
4 | * written by Colin Plumb in 1993, no copyright is claimed.
5 | * This code is in the public domain; do with it what you wish.
6 | *
7 | * Equivalent code is available from RSA Data Security, Inc.
8 | * This code has been tested against that, and is equivalent,
9 | * except that you don't need to include two pages of legalese
10 | * with every copy.
11 | *
12 | * To compute the message digest of a chunk of bytes, declare an
13 | * MD5Context structure, pass it to MD5Init, call MD5Update as
14 | * needed on buffers full of bytes, and then call MD5Final, which
15 | * will fill a supplied 16-byte array with the digest.
16 | */
17 |
18 | /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
19 | not require an integer type which is exactly 32 bits. This work
20 | draws on the changes for the same purpose by Tatu Ylonen
21 | as part of SSH, but since I didn't actually use
22 | that code, there is no copyright issue. I hereby disclaim
23 | copyright in any changes I have made; this code remains in the
24 | public domain. */
25 |
26 | #ifdef HAVE_CONFIG_H
27 | #include "config.h"
28 | #endif
29 |
30 | #if HAVE_STRING_H || STDC_HEADERS
31 | #include /* for memcpy() */
32 | #endif
33 |
34 | /* Add prototype support. */
35 | #ifndef PROTO
36 | #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
37 | #define PROTO(ARGS) ARGS
38 | #else
39 | #define PROTO(ARGS) ()
40 | #endif
41 | #endif
42 |
43 | #include "md5.h"
44 |
45 | /* Little-endian byte-swapping routines. Note that these do not
46 | depend on the size of datatypes such as uint32, nor do they require
47 | us to detect the endianness of the machine we are running on. It
48 | is possible they should be macros for speed, but I would be
49 | surprised if they were a performance bottleneck for MD5. */
50 |
51 | static uint32
52 | getu32 (addr)
53 | const unsigned char *addr;
54 | {
55 | return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
56 | | addr[1]) << 8 | addr[0];
57 | }
58 |
59 | static void
60 | putu32 (data, addr)
61 | uint32 data;
62 | unsigned char *addr;
63 | {
64 | addr[0] = (unsigned char)data;
65 | addr[1] = (unsigned char)(data >> 8);
66 | addr[2] = (unsigned char)(data >> 16);
67 | addr[3] = (unsigned char)(data >> 24);
68 | }
69 |
70 | /*
71 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
72 | * initialization constants.
73 | */
74 | void
75 | MD5Init(ctx)
76 | struct MD5Context *ctx;
77 | {
78 | ctx->buf[0] = 0x67452301;
79 | ctx->buf[1] = 0xefcdab89;
80 | ctx->buf[2] = 0x98badcfe;
81 | ctx->buf[3] = 0x10325476;
82 |
83 | ctx->bits[0] = 0;
84 | ctx->bits[1] = 0;
85 | }
86 |
87 | /*
88 | * Update context to reflect the concatenation of another buffer full
89 | * of bytes.
90 | */
91 | void
92 | MD5Update(ctx, buf, len)
93 | struct MD5Context *ctx;
94 | unsigned char const *buf;
95 | unsigned len;
96 | {
97 | uint32 t;
98 |
99 | /* Update bitcount */
100 |
101 | t = ctx->bits[0];
102 | if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
103 | ctx->bits[1]++; /* Carry from low to high */
104 | ctx->bits[1] += len >> 29;
105 |
106 | t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
107 |
108 | /* Handle any leading odd-sized chunks */
109 |
110 | if ( t ) {
111 | unsigned char *p = ctx->in + t;
112 |
113 | t = 64-t;
114 | if (len < t) {
115 | memcpy(p, buf, len);
116 | return;
117 | }
118 | memcpy(p, buf, t);
119 | MD5Transform(ctx->buf, ctx->in);
120 | buf += t;
121 | len -= t;
122 | }
123 |
124 | /* Process data in 64-byte chunks */
125 |
126 | while (len >= 64) {
127 | memcpy(ctx->in, buf, 64);
128 | MD5Transform(ctx->buf, ctx->in);
129 | buf += 64;
130 | len -= 64;
131 | }
132 |
133 | /* Handle any remaining bytes of data. */
134 |
135 | memcpy(ctx->in, buf, len);
136 | }
137 |
138 | /*
139 | * Final wrapup - pad to 64-byte boundary with the bit pattern
140 | * 1 0* (64-bit count of bits processed, MSB-first)
141 | */
142 | void
143 | MD5Final(digest, ctx)
144 | unsigned char digest[16];
145 | struct MD5Context *ctx;
146 | {
147 | unsigned count;
148 | unsigned char *p;
149 |
150 | /* Compute number of bytes mod 64 */
151 | count = (ctx->bits[0] >> 3) & 0x3F;
152 |
153 | /* Set the first char of padding to 0x80. This is safe since there is
154 | always at least one byte free */
155 | p = ctx->in + count;
156 | *p++ = 0x80;
157 |
158 | /* Bytes of padding needed to make 64 bytes */
159 | count = 64 - 1 - count;
160 |
161 | /* Pad out to 56 mod 64 */
162 | if (count < 8) {
163 | /* Two lots of padding: Pad the first block to 64 bytes */
164 | memset(p, 0, count);
165 | MD5Transform(ctx->buf, ctx->in);
166 |
167 | /* Now fill the next block with 56 bytes */
168 | memset(ctx->in, 0, 56);
169 | } else {
170 | /* Pad block to 56 bytes */
171 | memset(p, 0, count-8);
172 | }
173 |
174 | /* Append length in bits and transform */
175 | putu32(ctx->bits[0], ctx->in + 56);
176 | putu32(ctx->bits[1], ctx->in + 60);
177 |
178 | MD5Transform(ctx->buf, ctx->in);
179 | putu32(ctx->buf[0], digest);
180 | putu32(ctx->buf[1], digest + 4);
181 | putu32(ctx->buf[2], digest + 8);
182 | putu32(ctx->buf[3], digest + 12);
183 | memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
184 | }
185 |
186 | #ifndef ASM_MD5
187 |
188 | /* The four core functions - F1 is optimized somewhat */
189 |
190 | /* #define F1(x, y, z) (x & y | ~x & z) */
191 | #define F1(x, y, z) (z ^ (x & (y ^ z)))
192 | #define F2(x, y, z) F1(z, x, y)
193 | #define F3(x, y, z) (x ^ y ^ z)
194 | #define F4(x, y, z) (y ^ (x | ~z))
195 |
196 | /* This is the central step in the MD5 algorithm. */
197 | #define MD5STEP(f, w, x, y, z, data, s) \
198 | ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<>(32-s), w += x )
199 |
200 | /*
201 | * The core of the MD5 algorithm, this alters an existing MD5 hash to
202 | * reflect the addition of 16 longwords of new data. MD5Update blocks
203 | * the data and converts bytes into longwords for this routine.
204 | */
205 | void
206 | MD5Transform(buf, inraw)
207 | uint32 buf[4];
208 | const unsigned char inraw[64];
209 | {
210 | register uint32 a, b, c, d;
211 | uint32 in[16];
212 | int i;
213 |
214 | for (i = 0; i < 16; ++i)
215 | in[i] = getu32 (inraw + 4 * i);
216 |
217 | a = buf[0];
218 | b = buf[1];
219 | c = buf[2];
220 | d = buf[3];
221 |
222 | MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
223 | MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
224 | MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
225 | MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
226 | MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
227 | MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
228 | MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
229 | MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
230 | MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
231 | MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
232 | MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
233 | MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
234 | MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
235 | MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
236 | MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
237 | MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
238 |
239 | MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
240 | MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
241 | MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
242 | MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
243 | MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
244 | MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
245 | MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
246 | MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
247 | MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
248 | MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
249 | MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
250 | MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
251 | MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
252 | MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
253 | MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
254 | MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
255 |
256 | MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
257 | MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
258 | MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
259 | MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
260 | MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
261 | MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
262 | MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
263 | MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
264 | MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
265 | MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
266 | MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
267 | MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
268 | MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
269 | MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
270 | MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
271 | MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
272 |
273 | MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
274 | MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
275 | MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
276 | MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
277 | MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
278 | MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
279 | MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
280 | MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
281 | MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
282 | MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
283 | MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
284 | MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
285 | MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
286 | MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
287 | MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
288 | MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
289 |
290 | buf[0] += a;
291 | buf[1] += b;
292 | buf[2] += c;
293 | buf[3] += d;
294 | }
295 | #endif
296 |
297 | #ifdef TEST
298 | /* Simple test program. Can use it to manually run the tests from
299 | RFC1321 for example. */
300 | #include
301 |
302 | int
303 | main (int argc, char **argv)
304 | {
305 | struct MD5Context context;
306 | unsigned char checksum[16];
307 | int i;
308 | int j;
309 |
310 | if (argc < 2)
311 | {
312 | fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
313 | exit (1);
314 | }
315 | for (j = 1; j < argc; ++j)
316 | {
317 | printf ("MD5 (\"%s\") = ", argv[j]);
318 | MD5Init (&context);
319 | MD5Update (&context, argv[j], strlen (argv[j]));
320 | MD5Final (checksum, &context);
321 | for (i = 0; i < 16; i++)
322 | {
323 | printf ("%02x", (unsigned int) checksum[i]);
324 | }
325 | printf ("\n");
326 | }
327 | return 0;
328 | }
329 | #endif /* TEST */
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/md5.h:
--------------------------------------------------------------------------------
1 | /* See md5.c for explanation and copyright information. */
2 |
3 | #ifndef MD5_H
4 | #define MD5_H
5 |
6 | /* Unlike previous versions of this code, uint32 need not be exactly
7 | 32 bits, merely 32 bits or more. Choosing a data type which is 32
8 | bits instead of 64 is not important; speed is considerably more
9 | important. ANSI guarantees that "unsigned long" will be big enough,
10 | and always using it seems to have few disadvantages. */
11 | typedef unsigned long uint32;
12 |
13 | struct MD5Context {
14 | uint32 buf[4];
15 | uint32 bits[2];
16 | unsigned char in[64];
17 | };
18 |
19 | void MD5Init(struct MD5Context *context);
20 | void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
21 | void MD5Final(unsigned char digest[16], struct MD5Context *context);
22 | void MD5Transform(uint32 buf[4], const unsigned char in[64]);
23 |
24 | /*
25 | * This is needed to make RSAREF happy on some MS-DOS compilers.
26 | */
27 | typedef struct MD5Context MD5_CTX;
28 |
29 | #endif /* !MD5_H */
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/mdct.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: modified discrete cosine transform prototypes
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _OGG_mdct_H_
39 | #define _OGG_mdct_H_
40 |
41 | #include "ivorbiscodec.h"
42 | #include "misc.h"
43 |
44 | #define DATA_TYPE ogg_int32_t
45 | #define REG_TYPE register ogg_int32_t
46 |
47 | #ifdef _LOW_ACCURACY_
48 | #define cPI3_8 (0x0062)
49 | #define cPI2_8 (0x00b5)
50 | #define cPI1_8 (0x00ed)
51 | #else
52 | #define cPI3_8 (0x30fbc54d)
53 | #define cPI2_8 (0x5a82799a)
54 | #define cPI1_8 (0x7641af3d)
55 | #endif
56 |
57 | extern void mdct_backward(int n, DATA_TYPE *in);
58 | extern void mdct_shift_right(int n, DATA_TYPE *in, DATA_TYPE *right);
59 | extern void mdct_unroll_lap(int n0,int n1,
60 | int lW,int W,
61 | DATA_TYPE *in,DATA_TYPE *right,
62 | LOOKUP_T *w0,LOOKUP_T *w1,
63 | ogg_int16_t *out,
64 | int step,
65 | int start,int end /* samples, this frame */);
66 |
67 | #endif
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/misc.c:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************/
33 |
34 | #define HEAD_ALIGN 64
35 | #include
36 | #include
37 | #include
38 | #define MISC_C
39 | #include "misc.h"
40 | //#include
41 |
42 | static void **pointers=NULL;
43 | static long *insertlist=NULL; /* We can't embed this in the pointer list;
44 | a pointer can have any value... */
45 |
46 | static char **files=NULL;
47 | static long *file_bytes=NULL;
48 | static int filecount=0;
49 |
50 | static int ptop=0;
51 | static int palloced=0;
52 | static int pinsert=0;
53 |
54 | typedef struct {
55 | char *file;
56 | long line;
57 | long ptr;
58 | long bytes;
59 | } head;
60 |
61 | long global_bytes=0;
62 | long start_time=-1;
63 |
64 | static void *_insert(void *ptr,long bytes,char *file,long line){
65 | ((head *)ptr)->file=file;
66 | ((head *)ptr)->line=line;
67 | ((head *)ptr)->ptr=pinsert;
68 | ((head *)ptr)->bytes=bytes-HEAD_ALIGN;
69 |
70 | if(pinsert>=palloced){
71 | palloced+=64;
72 | if(pointers){
73 | pointers=(void **)realloc(pointers,sizeof(void **)*palloced);
74 | insertlist=(long *)realloc(insertlist,sizeof(long *)*palloced);
75 | }else{
76 | pointers=(void **)malloc(sizeof(void **)*palloced);
77 | insertlist=(long *)malloc(sizeof(long *)*palloced);
78 | }
79 | }
80 |
81 | pointers[pinsert]=ptr;
82 |
83 | if(pinsert==ptop)
84 | pinsert=++ptop;
85 | else
86 | pinsert=insertlist[pinsert];
87 |
88 | #ifdef _VDBG_GRAPHFILE
89 | {
90 | FILE *out;
91 | struct timeval tv;
92 | static struct timezone tz;
93 | int i;
94 | char buffer[80];
95 | gettimeofday(&tv,&tz);
96 |
97 | for(i=0;ifile;
152 | long bytes =((head *)ptr)->bytes;
153 | int i;
154 |
155 | gettimeofday(&tv,&tz);
156 | fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
157 | global_bytes);
158 | fprintf(out,"%ld, %ld\n",-start_time+(tv.tv_sec*1000)+(tv.tv_usec/1000),
159 | global_bytes-((head *)ptr)->bytes);
160 | fclose(out);
161 |
162 | for(i=0;ibytes;
181 |
182 | insert=((head *)ptr)->ptr;
183 | insertlist[insert]=pinsert;
184 | pinsert=insert;
185 |
186 | if(pointers[insert]==NULL){
187 | fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing previously freed memory\n");
188 | fprintf(stderr,"\t%s %ld\n",((head *)ptr)->file,((head *)ptr)->line);
189 | }
190 |
191 | if(global_bytes<0){
192 | fprintf(stderr,"DEBUGGING MALLOC ERROR: freeing unmalloced memory\n");
193 | }
194 |
195 | pointers[insert]=NULL;
196 | }
197 |
198 | void _VDBG_dump(void){
199 | int i;
200 | for(i=0;ifile,ptr->line);
205 | }
206 |
207 | }
208 |
209 | extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line){
210 | bytes+=HEAD_ALIGN;
211 | if(ptr){
212 | ptr=(void *)(((char *)ptr)-HEAD_ALIGN);
213 | _ripremove(ptr);
214 | ptr=realloc(ptr,bytes);
215 | }else{
216 | ptr=malloc(bytes);
217 | memset(ptr,0,bytes);
218 | }
219 | return _insert(ptr,bytes,file,line);
220 | }
221 |
222 | extern void _VDBG_free(void *ptr){
223 | if(ptr){
224 | ptr=(void *)(((char *)ptr)-HEAD_ALIGN);
225 | _ripremove(ptr);
226 | free(ptr);
227 | }
228 | }
229 |
230 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/misc.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: miscellaneous math and prototypes
35 |
36 | ************************************************************************/
37 |
38 | #ifndef _V_RANDOM_H_
39 | #define _V_RANDOM_H_
40 | #include "ivorbiscodec.h"
41 | #include "os_types.h"
42 |
43 | /*#define _VDBG_GRAPHFILE "_0.m"*/
44 |
45 |
46 | #ifdef _VDBG_GRAPHFILE
47 | extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line);
48 | extern void _VDBG_free(void *ptr);
49 |
50 | #undef _ogg_malloc
51 | #undef _ogg_calloc
52 | #undef _ogg_realloc
53 | #undef _ogg_free
54 |
55 | #define _ogg_malloc(x) _VDBG_malloc(NULL,(x),__FILE__,__LINE__)
56 | #define _ogg_calloc(x,y) _VDBG_malloc(NULL,(x)*(y),__FILE__,__LINE__)
57 | #define _ogg_realloc(x,y) _VDBG_malloc((x),(y),__FILE__,__LINE__)
58 | #define _ogg_free(x) _VDBG_free((x))
59 | #endif
60 |
61 | #include "asm_arm.h"
62 |
63 | #ifndef _V_WIDE_MATH
64 | #define _V_WIDE_MATH
65 |
66 | #ifndef _LOW_ACCURACY_
67 | /* 64 bit multiply */
68 |
69 | #include
70 | #include
71 |
72 | #if BYTE_ORDER==LITTLE_ENDIAN
73 | union magic {
74 | struct {
75 | ogg_int32_t lo;
76 | ogg_int32_t hi;
77 | } halves;
78 | ogg_int64_t whole;
79 | };
80 | #endif
81 |
82 | #if BYTE_ORDER==BIG_ENDIAN
83 | union magic {
84 | struct {
85 | ogg_int32_t hi;
86 | ogg_int32_t lo;
87 | } halves;
88 | ogg_int64_t whole;
89 | };
90 | #endif
91 |
92 | static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) {
93 | union magic magic;
94 | magic.whole = (ogg_int64_t)x * y;
95 | return magic.halves.hi;
96 | }
97 |
98 | static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) {
99 | return MULT32(x,y)<<1;
100 | }
101 |
102 | static inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) {
103 | union magic magic;
104 | magic.whole = (ogg_int64_t)x * y;
105 | return ((ogg_uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17);
106 | }
107 |
108 | #else
109 | /* 32 bit multiply, more portable but less accurate */
110 |
111 | /*
112 | * Note: Precision is biased towards the first argument therefore ordering
113 | * is important. Shift values were chosen for the best sound quality after
114 | * many listening tests.
115 | */
116 |
117 | /*
118 | * For MULT32 and MULT31: The second argument is always a lookup table
119 | * value already preshifted from 31 to 8 bits. We therefore take the
120 | * opportunity to save on text space and use unsigned char for those
121 | * tables in this case.
122 | */
123 |
124 | static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) {
125 | return (x >> 9) * y; /* y preshifted >>23 */
126 | }
127 |
128 | static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) {
129 | return (x >> 8) * y; /* y preshifted >>23 */
130 | }
131 |
132 | static inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) {
133 | return (x >> 6) * y; /* y preshifted >>9 */
134 | }
135 |
136 | #endif
137 |
138 | /*
139 | * This should be used as a memory barrier, forcing all cached values in
140 | * registers to wr writen back to memory. Might or might not be beneficial
141 | * depending on the architecture and compiler.
142 | */
143 | #define MB()
144 |
145 | /*
146 | * The XPROD functions are meant to optimize the cross products found all
147 | * over the place in mdct.c by forcing memory operation ordering to avoid
148 | * unnecessary register reloads as soon as memory is being written to.
149 | * However this is only beneficial on CPUs with a sane number of general
150 | * purpose registers which exclude the Intel x86. On Intel, better let the
151 | * compiler actually reload registers directly from original memory by using
152 | * macros.
153 | */
154 |
155 | #ifdef __i386__
156 |
157 | #define XPROD32(_a, _b, _t, _v, _x, _y) \
158 | { *(_x)=MULT32(_a,_t)+MULT32(_b,_v); \
159 | *(_y)=MULT32(_b,_t)-MULT32(_a,_v); }
160 | #define XPROD31(_a, _b, _t, _v, _x, _y) \
161 | { *(_x)=MULT31(_a,_t)+MULT31(_b,_v); \
162 | *(_y)=MULT31(_b,_t)-MULT31(_a,_v); }
163 | #define XNPROD31(_a, _b, _t, _v, _x, _y) \
164 | { *(_x)=MULT31(_a,_t)-MULT31(_b,_v); \
165 | *(_y)=MULT31(_b,_t)+MULT31(_a,_v); }
166 |
167 | #else
168 |
169 | static inline void XPROD32(ogg_int32_t a, ogg_int32_t b,
170 | ogg_int32_t t, ogg_int32_t v,
171 | ogg_int32_t *x, ogg_int32_t *y)
172 | {
173 | *x = MULT32(a, t) + MULT32(b, v);
174 | *y = MULT32(b, t) - MULT32(a, v);
175 | }
176 |
177 | static inline void XPROD31(ogg_int32_t a, ogg_int32_t b,
178 | ogg_int32_t t, ogg_int32_t v,
179 | ogg_int32_t *x, ogg_int32_t *y)
180 | {
181 | *x = MULT31(a, t) + MULT31(b, v);
182 | *y = MULT31(b, t) - MULT31(a, v);
183 | }
184 |
185 | static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b,
186 | ogg_int32_t t, ogg_int32_t v,
187 | ogg_int32_t *x, ogg_int32_t *y)
188 | {
189 | *x = MULT31(a, t) - MULT31(b, v);
190 | *y = MULT31(b, t) + MULT31(a, v);
191 | }
192 |
193 | #endif
194 |
195 | #endif
196 |
197 | #ifndef _V_CLIP_MATH
198 | #define _V_CLIP_MATH
199 |
200 | static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
201 | int ret=x;
202 | ret-= ((x<=32767)-1)&(x-32767);
203 | ret-= ((x>=-32768)-1)&(x+32768);
204 | return(ret);
205 | }
206 |
207 | #endif
208 |
209 | #endif
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/ogg.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: subsumed libogg includes
35 |
36 | ************************************************************************/
37 | #ifndef _OGG_H
38 | #define _OGG_H
39 |
40 | #ifdef __cplusplus
41 | extern "C" {
42 | #endif
43 |
44 | #include "os_types.h"
45 |
46 | #ifndef ONLY_C
47 | #define ARM_LITTLE_ENDIAN
48 | #endif
49 |
50 | typedef struct ogg_buffer_state{
51 | struct ogg_buffer *unused_buffers;
52 | struct ogg_reference *unused_references;
53 | int outstanding;
54 | int shutdown;
55 | } ogg_buffer_state;
56 |
57 | typedef struct ogg_buffer {
58 | unsigned char *data;
59 | long size;
60 | int refcount;
61 |
62 | union {
63 | ogg_buffer_state *owner;
64 | struct ogg_buffer *next;
65 | } ptr;
66 | } ogg_buffer;
67 |
68 | typedef struct ogg_reference {
69 | ogg_buffer *buffer;
70 | long begin;
71 | long length;
72 |
73 | struct ogg_reference *next;
74 | } ogg_reference;
75 |
76 | typedef struct oggpack_buffer {
77 | #ifdef ARM_LITTLE_ENDIAN
78 | int bitsLeftInSegment;
79 | ogg_uint32_t *ptr;
80 | long bitsLeftInWord;
81 | #else
82 | int headbit;
83 | unsigned char *headptr;
84 | long headend;
85 | #endif /* ARM_LITTLE_ENDIAN */
86 | /* memory management */
87 | ogg_reference *head;
88 | ogg_reference *tail;
89 |
90 | /* render the byte/bit counter API constant time */
91 | long count; /* doesn't count the tail */
92 | } oggpack_buffer;
93 |
94 | typedef struct oggbyte_buffer {
95 | ogg_reference *baseref;
96 |
97 | ogg_reference *ref;
98 | unsigned char *ptr;
99 | long pos;
100 | long end;
101 | } oggbyte_buffer;
102 |
103 | typedef struct ogg_sync_state {
104 | /* decode memory management pool */
105 | ogg_buffer_state *bufferpool;
106 |
107 | /* stream buffers */
108 | ogg_reference *fifo_head;
109 | ogg_reference *fifo_tail;
110 | long fifo_fill;
111 |
112 | /* stream sync management */
113 | int unsynced;
114 | int headerbytes;
115 | int bodybytes;
116 |
117 | } ogg_sync_state;
118 |
119 | typedef struct ogg_stream_state {
120 | ogg_reference *header_head;
121 | ogg_reference *header_tail;
122 | ogg_reference *body_head;
123 | ogg_reference *body_tail;
124 |
125 | int e_o_s; /* set when we have buffered the last
126 | packet in the logical bitstream */
127 | int b_o_s; /* set after we've written the initial page
128 | of a logical bitstream */
129 | long serialno;
130 | long pageno;
131 | ogg_int64_t packetno; /* sequence number for decode; the framing
132 | knows where there's a hole in the data,
133 | but we need coupling so that the codec
134 | (which is in a seperate abstraction
135 | layer) also knows about the gap */
136 | ogg_int64_t granulepos;
137 |
138 | int lacing_fill;
139 | ogg_uint32_t body_fill;
140 |
141 | /* decode-side state data */
142 | int holeflag;
143 | int spanflag;
144 | int clearflag;
145 | int laceptr;
146 | ogg_uint32_t body_fill_next;
147 |
148 | } ogg_stream_state;
149 |
150 | typedef struct {
151 | ogg_reference *packet;
152 | long bytes;
153 | long b_o_s;
154 | long e_o_s;
155 | ogg_int64_t granulepos;
156 | ogg_int64_t packetno; /* sequence number for decode; the framing
157 | knows where there's a hole in the data,
158 | but we need coupling so that the codec
159 | (which is in a seperate abstraction
160 | layer) also knows about the gap */
161 | } ogg_packet;
162 |
163 | typedef struct {
164 | ogg_reference *header;
165 | int header_len;
166 | ogg_reference *body;
167 | long body_len;
168 | } ogg_page;
169 |
170 | /* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
171 |
172 | extern void oggpack_readinit(oggpack_buffer *b,ogg_reference *r);
173 | extern long oggpack_look(oggpack_buffer *b,int bits);
174 | extern void oggpack_adv(oggpack_buffer *b,int bits);
175 | extern long oggpack_read(oggpack_buffer *b,int bits);
176 | extern long oggpack_bytes(oggpack_buffer *b);
177 | extern long oggpack_bits(oggpack_buffer *b);
178 | extern int oggpack_eop(oggpack_buffer *b);
179 |
180 | // Quick hack
181 | #define oggpack_bytesleft(B) (((B)->bitsLeftInSegment+7)/8)
182 |
183 | /* Ogg BITSTREAM PRIMITIVES: decoding **************************/
184 |
185 | extern void ogg_sync_init(ogg_sync_state *oy);
186 | extern ogg_sync_state *ogg_sync_create(void);
187 | extern int ogg_sync_clear(ogg_sync_state *oy);
188 | extern int ogg_sync_destroy(ogg_sync_state *oy);
189 | extern int ogg_sync_reset(ogg_sync_state *oy);
190 |
191 | extern unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long size);
192 | extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
193 | extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
194 | extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
195 | extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
196 | extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
197 | extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
198 |
199 | /* Ogg BITSTREAM PRIMITIVES: general ***************************/
200 |
201 | extern void ogg_stream_init(ogg_stream_state *os, int serialno);
202 | extern ogg_stream_state *ogg_stream_create(int serialno);
203 | extern int ogg_stream_destroy(ogg_stream_state *os);
204 | extern int ogg_stream_clear(ogg_stream_state *os);
205 | extern int ogg_stream_reset(ogg_stream_state *os);
206 | extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
207 | extern int ogg_stream_eos(ogg_stream_state *os);
208 |
209 | extern int ogg_page_checksum_set(ogg_page *og);
210 |
211 | extern int ogg_page_version(ogg_page *og);
212 | extern int ogg_page_continued(ogg_page *og);
213 | extern int ogg_page_bos(ogg_page *og);
214 | extern int ogg_page_eos(ogg_page *og);
215 | extern ogg_int64_t ogg_page_granulepos(ogg_page *og);
216 | extern ogg_uint32_t ogg_page_serialno(ogg_page *og);
217 | extern ogg_uint32_t ogg_page_pageno(ogg_page *og);
218 | extern int ogg_page_packets(ogg_page *og);
219 | extern int ogg_page_getbuffer(ogg_page *og, unsigned char **buffer);
220 |
221 | extern int ogg_packet_release(ogg_packet *op);
222 | extern int ogg_page_release(ogg_page *og);
223 |
224 | extern void ogg_page_dup(ogg_page *d, ogg_page *s);
225 |
226 | /* Ogg BITSTREAM PRIMITIVES: return codes ***************************/
227 |
228 | #define OGG_SUCCESS 0
229 |
230 | #define OGG_HOLE -10
231 | #define OGG_SPAN -11
232 | #define OGG_EVERSION -12
233 | #define OGG_ESERIAL -13
234 | #define OGG_EINVAL -14
235 | #define OGG_EEOS -15
236 |
237 |
238 | #ifdef __cplusplus
239 | }
240 | #endif
241 |
242 | #endif /* _OGG_H */
243 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/os.h:
--------------------------------------------------------------------------------
1 | #ifndef _OS_H
2 | #define _OS_H
3 | /************************************************************************
4 | * Copyright (C) 2002-2009, Xiph.org Foundation
5 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
6 | * All rights reserved.
7 | *
8 | * Redistribution and use in source and binary forms, with or without
9 | * modification, are permitted provided that the following conditions
10 | * are met:
11 | *
12 | * * Redistributions of source code must retain the above copyright
13 | * notice, this list of conditions and the following disclaimer.
14 | * * Redistributions in binary form must reproduce the above
15 | * copyright notice, this list of conditions and the following disclaimer
16 | * in the documentation and/or other materials provided with the
17 | * distribution.
18 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
19 | * Productions Ltd nor the names of its contributors may be used to
20 | * endorse or promote products derived from this software without
21 | * specific prior written permission.
22 | *
23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 | ************************************************************************
35 |
36 | function: #ifdef jail to whip a few platforms into the UNIX ideal.
37 |
38 | ************************************************************************/
39 |
40 | #include
41 | #include "os_types.h"
42 |
43 | #ifndef _V_IFDEFJAIL_H_
44 | # define _V_IFDEFJAIL_H_
45 |
46 | # ifdef __GNUC__
47 | # define STIN static __inline__
48 | # elif _WIN32
49 | # define STIN static __inline
50 | # endif
51 | #else
52 | # define STIN static
53 | #endif
54 |
55 | #ifndef M_PI
56 | # define M_PI (3.1415926536f)
57 | #endif
58 |
59 | #ifdef _WIN32
60 | # include
61 | # define rint(x) (floor((x)+0.5f))
62 | # define NO_FLOAT_MATH_LIB
63 | # define FAST_HYPOT(a, b) sqrt((a)*(a) + (b)*(b))
64 | #endif
65 |
66 | #ifdef HAVE_ALLOCA_H
67 | # include
68 | #endif
69 |
70 | #ifdef USE_MEMORY_H
71 | # include
72 | #endif
73 |
74 | #ifndef min
75 | # define min(x,y) ((x)>(y)?(y):(x))
76 | #endif
77 |
78 | #ifndef max
79 | # define max(x,y) ((x)<(y)?(y):(x))
80 | #endif
81 |
82 | #endif /* _OS_H */
83 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/os_types.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: #ifdef jail to whip a few platforms into the UNIX ideal.
35 |
36 | ************************************************************************/
37 | #ifndef _OS_TYPES_H
38 | #define _OS_TYPES_H
39 |
40 | #ifdef _LOW_ACCURACY_
41 | # define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9))
42 | # define LOOKUP_T const unsigned char
43 | #else
44 | # define X(n) (n)
45 | # define LOOKUP_T const ogg_int32_t
46 | #endif
47 |
48 | /* make it easy on the folks that want to compile the libs with a
49 | different malloc than stdlib */
50 | #define _ogg_malloc malloc
51 | #define _ogg_calloc calloc
52 | #define _ogg_realloc realloc
53 | #define _ogg_free free
54 |
55 | #if defined (_WIN32_WCE)
56 |
57 | typedef unsigned short ogg_uint16_t;
58 | typedef short ogg_int16_t;
59 | typedef int ogg_int32_t;
60 | typedef unsigned int ogg_uint32_t;
61 | typedef __int64 ogg_int64_t;
62 |
63 | #define inline
64 |
65 | #elif defined(_WIN32)
66 |
67 | # ifndef __GNUC__
68 | /* MSVC/Borland */
69 | typedef __int64 ogg_int64_t;
70 | typedef __int32 ogg_int32_t;
71 | typedef unsigned __int32 ogg_uint32_t;
72 | typedef __int16 ogg_int16_t;
73 | typedef unsigned __int16 ogg_uint16_t;
74 | # else
75 | /* Cygwin */
76 | #include <_G_config.h>
77 | typedef _G_int64_t ogg_int64_t;
78 | typedef _G_int32_t ogg_int32_t;
79 | typedef _G_uint32_t ogg_uint32_t;
80 | typedef _G_int16_t ogg_int16_t;
81 | typedef _G_uint16_t ogg_uint16_t;
82 | # endif
83 |
84 | #elif defined(__MACOS__)
85 |
86 | # include
87 | typedef SInt16 ogg_int16_t;
88 | typedef UInt16 ogg_uint16_t;
89 | typedef SInt32 ogg_int32_t;
90 | typedef UInt32 ogg_uint32_t;
91 | typedef SInt64 ogg_int64_t;
92 |
93 | #elif defined(__MACOSX__) /* MacOS X Framework build */
94 |
95 | # include
96 | typedef int16_t ogg_int16_t;
97 | typedef u_int16_t ogg_uint16_t;
98 | typedef int32_t ogg_int32_t;
99 | typedef u_int32_t ogg_uint32_t;
100 | typedef int64_t ogg_int64_t;
101 |
102 | #elif defined(__BEOS__)
103 |
104 | /* Be */
105 | # include
106 |
107 | #elif defined (__EMX__)
108 |
109 | /* OS/2 GCC */
110 | typedef short ogg_int16_t;
111 | typedef unsigned short ogg_uint16_t;
112 | typedef int ogg_int32_t;
113 | typedef unsigned int ogg_uint32_t;
114 | typedef long long ogg_int64_t;
115 |
116 | #else
117 |
118 | # include
119 | # include "config_types.h"
120 | # include
121 |
122 | #endif
123 |
124 | #endif /* _OS_TYPES_H */
125 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/res012.c:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | * Copyright (C) 2002-2009, Xiph.org Foundation
3 | * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * * Redistributions in binary form must reproduce the above
13 | * copyright notice, this list of conditions and the following disclaimer
14 | * in the documentation and/or other materials provided with the
15 | * distribution.
16 | * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 | * Productions Ltd nor the names of its contributors may be used to
18 | * endorse or promote products derived from this software without
19 | * specific prior written permission.
20 | *
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | ************************************************************************
33 |
34 | function: residue backend 0, 1 and 2 implementation
35 |
36 | ************************************************************************/
37 |
38 | #include
39 | #include
40 | #include
41 | #include "ogg.h"
42 | #include "ivorbiscodec.h"
43 | #include "codec_internal.h"
44 | #include "codebook.h"
45 | #include "misc.h"
46 | #include "os.h"
47 |
48 | void res_clear_info(vorbis_info_residue *info){
49 | if(info){
50 | if(info->stagemasks)_ogg_free(info->stagemasks);
51 | if(info->stagebooks)_ogg_free(info->stagebooks);
52 | memset(info,0,sizeof(*info));
53 | }
54 | }
55 |
56 |
57 | /* vorbis_info is for range checking */
58 | int res_unpack(vorbis_info_residue *info,
59 | vorbis_info *vi,oggpack_buffer *opb){
60 | int j,k;
61 | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
62 | memset(info,0,sizeof(*info));
63 |
64 | info->type=oggpack_read(opb,16);
65 | if(info->type>2 || info->type<0)goto errout;
66 | info->begin=oggpack_read(opb,24);
67 | info->end=oggpack_read(opb,24);
68 | info->grouping=oggpack_read(opb,24)+1; // "partition size" in spec
69 | info->partitions=(char)(oggpack_read(opb,6)+1); // "classification" in spec
70 | info->groupbook=(unsigned char)oggpack_read(opb,8); // "classbook" in spec
71 | if(info->groupbook>=ci->books)goto errout;
72 |
73 | info->stagemasks=_ogg_malloc(info->partitions*sizeof(*info->stagemasks));
74 | info->stagebooks=_ogg_malloc(info->partitions*8*sizeof(*info->stagebooks));
75 |
76 | for(j=0;jpartitions;j++){
77 | int cascade=oggpack_read(opb,3);
78 | if(oggpack_read(opb,1))
79 | cascade|=(oggpack_read(opb,5)<<3);
80 | info->stagemasks[j]=cascade;
81 | }
82 |
83 | for(j=0;jpartitions;j++){
84 | for(k=0;k<8;k++){
85 | if((info->stagemasks[j]>>k)&1){
86 | unsigned char book=(unsigned char)oggpack_read(opb,8);
87 | if(book>=ci->books)goto errout;
88 | info->stagebooks[j*8+k]=book;
89 | if(k+1>info->stages)info->stages=k+1;
90 | }else
91 | info->stagebooks[j*8+k]=0xff;
92 | }
93 | }
94 |
95 | if(oggpack_eop(opb))goto errout;
96 |
97 | // According to the Vorbis spec (paragraph 8.6.2 "packet decode"), residue
98 | // begin and end should be limited to the maximum possible vector size in
99 | // case they exceed it. However doing that makes the decoder crash further
100 | // down, so we return an error instead.
101 | int limit = (info->type == 2 ? vi->channels : 1) * ci->blocksizes[1] / 2;
102 | if (info->begin > info->end ||
103 | info->end > limit) {
104 | goto errout;
105 | }
106 | return 0;
107 | errout:
108 | res_clear_info(info);
109 | return 1;
110 | }
111 |
112 | int res_inverse(vorbis_dsp_state *vd,vorbis_info_residue *info,
113 | ogg_int32_t **in,int *nonzero,int ch){
114 |
115 | int i,j,k,s,used=0;
116 | codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup;
117 | codebook *phrasebook=ci->book_param+info->groupbook;
118 | int samples_per_partition=info->grouping;
119 | int partitions_per_word=phrasebook->dim;
120 | int pcmend=ci->blocksizes[vd->W];
121 |
122 | if(info->type<2){
123 | int max=pcmend>>1;
124 | int end=(info->endend:max);
125 | int n=end-info->begin;
126 |
127 | if(n>0){
128 | int partvals=n/samples_per_partition;
129 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
130 |
131 | for(i=0;istages;s++){
147 |
148 | for(i=0;i=0;k--)
154 | partword[0][i+k]=partword[0][i+k+1]*info->partitions;
155 |
156 | for(j=1;j=0;k--)
158 | partword[j][i+k]=partword[j-1][i+k];
159 |
160 | for(j=0;jopb);
162 | if(temp==-1)goto cleanup1;
163 |
164 | /* this can be done quickly in assembly due to the quotient
165 | always being at most six bits */
166 | for(k=0;kbegin+i*samples_per_partition;
179 | int idx = (int)partword[j][i];
180 | if(idx < info->partitions && info->stagemasks[idx]&(1<book_param+
182 | info->stagebooks[(partword[j][i]<<3)+s];
183 | if(info->type){
184 | if(vorbis_book_decodev_add(stagebook,in[j]+offset,&vd->opb,
185 | samples_per_partition,-8)==-1)
186 | goto cleanup1;
187 | }else{
188 | if(vorbis_book_decodevs_add(stagebook,in[j]+offset,&vd->opb,
189 | samples_per_partition,-8)==-1)
190 | goto cleanup1;
191 | }
192 | }
193 | }
194 | }
195 | }
196 | cleanup1:
197 | if(partword){
198 | for(j=0;j>1;
207 | int end=(info->endend:max);
208 | int n=end-info->begin;
209 |
210 | if(n>0){
211 | int partvals=n/samples_per_partition;
212 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
213 |
214 | char *partword=
215 | (char *)_ogg_malloc(partwords*partitions_per_word*sizeof(*partword));
216 | if(partword==NULL)goto cleanup2;
217 | int beginoff=info->begin/ch;
218 |
219 | for(i=0;istages;s++){
225 | for(i=0;i=0;k--)
231 | partword[i+k]=partword[i+k+1]*info->partitions;
232 |
233 | /* fetch the partition word */
234 | temp=vorbis_book_decode(phrasebook,&vd->opb);
235 | if(temp==-1)goto cleanup2;
236 |
237 | /* this can be done quickly in assembly due to the quotient
238 | always being at most six bits */
239 | for(k=0;k= 0 && partword[i] < info->partitions &&
249 | (info->stagemasks[(int)partword[i]] & (1 << s))){
250 | codebook *stagebook=ci->book_param+
251 | info->stagebooks[(partword[i]<<3)+s];
252 | if(vorbis_book_decodevv_add(stagebook,in,
253 | i*samples_per_partition+beginoff,ch,
254 | &vd->opb,
255 | samples_per_partition,-8)==-1)
256 | goto cleanup2;
257 | }
258 | }
259 | }
260 | }
261 | cleanup2:
262 | if(partword)_ogg_free(partword);
263 | }
264 | }
265 |
266 | return 0;
267 | }
268 |
269 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/jni/libtremolo/tremolo-jni.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "ivorbiscodec.h"
11 | #include "ivorbisfile.h"
12 |
13 | struct JniParams {
14 | JNIEnv *env;
15 | jobject obj;
16 | void *jniBuffer;
17 | jmethodID writeOgg;
18 | jmethodID seekOgg;
19 | jmethodID tellOgg;
20 | int current_section;
21 | };
22 |
23 | static size_t oggRead(void *ptr, size_t size, size_t nmemb, void *datasource){
24 | struct JniParams *params = datasource;
25 | int written = (*params->env)->CallIntMethod(params->env, params->obj, params->writeOgg, 1 * nmemb);
26 | if(written > 0){
27 | memcpy(ptr, params->jniBuffer, written);
28 | }
29 |
30 | return written;
31 | }
32 |
33 | static int oggSeek(void *datasource, ogg_int64_t offset, int whence)
34 | {
35 | struct JniParams *params = datasource;
36 |
37 | int result = (*params->env)->CallIntMethod(params->env, params->obj, params->seekOgg, offset, whence);
38 |
39 | return result;
40 | }
41 |
42 | static long oggTell(void *datasource)
43 | {
44 | struct JniParams *params = datasource;
45 | int position = (*params->env)->CallIntMethod(params->env, params->obj, params->tellOgg);
46 | return position;
47 | }
48 |
49 | JNIEXPORT jlong JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_initDecoder(JNIEnv *env, jobject obj, jobject jJjniBuffer)
50 | {
51 | void *jniBuffer = (*env)->GetDirectBufferAddress(env, jJjniBuffer);
52 |
53 | jclass cls = (*env)->GetObjectClass(env, obj);
54 |
55 | jmethodID writeOgg = (*env)->GetMethodID(env, cls, "writeOgg", "(I)I");
56 | jmethodID seekOgg = (*env)->GetMethodID(env, cls, "seekOgg", "(JI)I");
57 | jmethodID tellOgg = (*env)->GetMethodID(env, cls, "tellOgg", "()I");
58 |
59 | struct JniParams *params;
60 | params = (struct JniParams *)malloc(sizeof(struct JniParams));
61 | params->env = env;
62 | params->jniBuffer = jniBuffer;
63 | params->writeOgg = writeOgg;
64 | params->seekOgg = seekOgg;
65 | params->tellOgg = tellOgg;
66 | params->obj = obj;
67 |
68 | struct OggVorbis_File *vf;
69 | vf = (struct OggVorbis_File *)malloc(sizeof(struct OggVorbis_File));
70 |
71 | ov_callbacks callbacks = {
72 | (size_t (*)(void *, size_t, size_t, void *)) oggRead,
73 | (int (*)(void *, ogg_int64_t, int)) oggSeek, //noseek
74 | (int (*)(void *)) fclose,
75 | (long (*)(void *)) oggTell // notell
76 | };
77 |
78 | if(ov_open_callbacks(params, vf, NULL, 0, callbacks) < 0) {
79 | // Input does not appear to be an Ogg bitstream
80 | return 0;
81 | }
82 |
83 | jlong pointer = (jlong) vf;
84 | return pointer;
85 | }
86 |
87 | JNIEXPORT jlong JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_read(JNIEnv *env, jobject obj, jlong jHandle, jint jLen)
88 | {
89 | struct OggVorbis_File *vf;
90 | vf = (struct OggVorbis_File *)jHandle;
91 |
92 | struct JniParams *params = vf->datasource;
93 | params->env = env;
94 | params->obj = obj;
95 |
96 | return ov_read(vf,params->jniBuffer,jLen,¶ms->current_section);
97 | }
98 |
99 | JNIEXPORT jint JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_seekMs(JNIEnv *env, jobject obj, jlong jHandle, jint jMilliseconds)
100 | {
101 | struct OggVorbis_File *vf;
102 | vf = (struct OggVorbis_File *)jHandle;
103 |
104 | struct JniParams *params = vf->datasource;
105 | params->env = env;
106 | params->obj = obj;
107 | return ov_time_seek(vf, jMilliseconds);
108 | }
109 |
110 | JNIEXPORT jint JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_seekSamples(JNIEnv *env, jobject obj, jlong jHandle, jint jSamples)
111 | {
112 | struct OggVorbis_File *vf;
113 | vf = (struct OggVorbis_File *)jHandle;
114 |
115 | struct JniParams *params = vf->datasource;
116 | params->env = env;
117 | params->obj = obj;
118 | return ov_pcm_seek(vf, jSamples);
119 | }
120 |
121 | JNIEXPORT jlong JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_tellMs(JNIEnv *env, jobject obj, jlong jHandle)
122 | {
123 | struct OggVorbis_File *vf;
124 | vf = (struct OggVorbis_File *)jHandle;
125 |
126 | struct JniParams *params = vf->datasource;
127 | params->env = env;
128 | params->obj = obj;
129 | return ov_time_tell(vf);
130 | }
131 |
132 | JNIEXPORT jlong JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_tellSamples(JNIEnv *env, jobject obj, jlong jHandle)
133 | {
134 | struct OggVorbis_File *vf;
135 | vf = (struct OggVorbis_File *)jHandle;
136 |
137 | struct JniParams *params = vf->datasource;
138 | params->env = env;
139 | params->obj = obj;
140 | return ov_pcm_tell(vf);
141 | }
142 |
143 | JNIEXPORT jlong JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_totalSamples(JNIEnv *env, jobject obj, jlong jHandle)
144 | {
145 | struct OggVorbis_File *vf;
146 | vf = (struct OggVorbis_File *)jHandle;
147 |
148 | struct JniParams *params = vf->datasource;
149 | params->env = env;
150 | params->obj = obj;
151 | return ov_pcm_total(vf,-1);
152 | }
153 |
154 | JNIEXPORT void JNICALL Java_xyz_gianlu_librespot_player_decoders_tremolo_OggDecodingInputStream_close(JNIEnv *env, jobject obj, jlong jHandle)
155 | {
156 | struct OggVorbis_File *vf;
157 | vf = (struct OggVorbis_File *)jHandle;
158 | struct JniParams *params = vf->datasource;
159 |
160 | free(params);
161 | vf->datasource = NULL;
162 | ov_clear(vf);
163 | free(vf);
164 | vf = NULL;
165 | }
166 |
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/libs/arm64-v8a/libtremolo.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/librespot-android-decoder-tremolo/src/main/libs/arm64-v8a/libtremolo.so
--------------------------------------------------------------------------------
/librespot-android-decoder-tremolo/src/main/libs/armeabi-v7a/libtremolo.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/librespot-android-decoder-tremolo/src/main/libs/armeabi-v7a/libtremolo.so
--------------------------------------------------------------------------------
/librespot-android-decoder/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/librespot-android-decoder/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'maven-publish'
4 | }
5 |
6 | android {
7 | compileSdkVersion 31
8 | buildToolsVersion "30.0.3"
9 |
10 | defaultConfig {
11 | minSdkVersion 23
12 | targetSdkVersion 31
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 |
24 | compileOptions {
25 | sourceCompatibility JavaVersion.VERSION_1_8
26 | targetCompatibility JavaVersion.VERSION_1_8
27 | }
28 | }
29 |
30 | dependencies {
31 | implementation 'xyz.gianlu.librespot:librespot-decoder-api:1.6.2'
32 | }
--------------------------------------------------------------------------------
/librespot-android-decoder/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/librespot-android-decoder/src/main/java/xyz/gianlu/librespot/player/decoders/AndroidNativeDecoder.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.player.decoders;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.MediaCodec;
5 | import android.media.MediaDataSource;
6 | import android.media.MediaExtractor;
7 | import android.media.MediaFormat;
8 | import android.os.Build;
9 | import android.util.Log;
10 |
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | import java.io.IOException;
14 | import java.io.OutputStream;
15 | import java.nio.ByteBuffer;
16 | import java.util.concurrent.TimeUnit;
17 |
18 | import xyz.gianlu.librespot.player.mixing.output.OutputAudioFormat;
19 |
20 | public final class AndroidNativeDecoder extends Decoder {
21 | private static final String TAG = AndroidNativeDecoder.class.getSimpleName();
22 | private final byte[] buffer = new byte[2 * BUFFER_SIZE];
23 | private final MediaCodec codec;
24 | private final MediaExtractor extractor;
25 | private final Object closeLock = new Object();
26 | private long presentationTime = 0;
27 |
28 | public AndroidNativeDecoder(@NotNull SeekableInputStream audioIn, float normalizationFactor, int duration) throws IOException, DecoderException {
29 | super(audioIn, normalizationFactor, duration);
30 |
31 | int start = audioIn.position();
32 | extractor = new MediaExtractor();
33 | extractor.setDataSource(new MediaDataSource() {
34 | @Override
35 | public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
36 | audioIn.seek((int) position + start);
37 | return audioIn.read(buffer, offset, size);
38 | }
39 |
40 | @Override
41 | public long getSize() {
42 | return audioIn.size() - start;
43 | }
44 |
45 | @Override
46 | public void close() {
47 | audioIn.close();
48 | }
49 | });
50 |
51 | if (extractor.getTrackCount() == 0)
52 | throw new DecoderException("No tracks found.");
53 |
54 | extractor.selectTrack(0);
55 |
56 | MediaFormat format = extractor.getTrackFormat(0);
57 |
58 | codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
59 | codec.configure(format, null, null, 0);
60 | codec.start();
61 |
62 | int sampleSize = 16;
63 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
64 | switch (format.getInteger(MediaFormat.KEY_PCM_ENCODING, AudioFormat.ENCODING_PCM_16BIT)) {
65 | case AudioFormat.ENCODING_PCM_8BIT:
66 | sampleSize = 8;
67 | break;
68 | case AudioFormat.ENCODING_PCM_16BIT:
69 | sampleSize = 16;
70 | break;
71 | default:
72 | throw new DecoderException("Unsupported PCM encoding.");
73 | }
74 | }
75 |
76 | setAudioFormat(new OutputAudioFormat(format.getInteger(MediaFormat.KEY_SAMPLE_RATE), sampleSize,
77 | format.getInteger(MediaFormat.KEY_CHANNEL_COUNT), true, false));
78 | }
79 |
80 | @Override
81 | protected int readInternal(@NotNull OutputStream out) throws IOException {
82 | MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
83 |
84 | while (true) {
85 | if (closed) return -1;
86 |
87 | synchronized (closeLock) {
88 | int inputBufferId = codec.dequeueInputBuffer(-1);
89 | if (inputBufferId >= 0) {
90 | ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
91 | int count = extractor.readSampleData(inputBuffer, 0);
92 | if (count == -1) {
93 | codec.signalEndOfInputStream();
94 | return -1;
95 | }
96 | codec.queueInputBuffer(inputBufferId, inputBuffer.position(), inputBuffer.limit(), extractor.getSampleTime(), 0);
97 | extractor.advance();
98 | }
99 |
100 | int outputBufferId = codec.dequeueOutputBuffer(info, 10000);
101 | if (outputBufferId >= 0) {
102 | ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
103 |
104 | while (outputBuffer.remaining() > 0) {
105 | int read = Math.min(outputBuffer.remaining(), buffer.length);
106 | outputBuffer.get(buffer, 0, read);
107 | out.write(buffer, 0, read);
108 | }
109 |
110 | codec.releaseOutputBuffer(outputBufferId, false);
111 | presentationTime = TimeUnit.MICROSECONDS.toMillis(info.presentationTimeUs);
112 | return info.size;
113 | } else if (outputBufferId == MediaCodec.INFO_TRY_AGAIN_LATER) {
114 | Log.d(TAG, "Timeout");
115 | } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
116 | Log.d(TAG, "Output buffers changed");
117 | } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
118 | Log.d(TAG, "Output format changed: " + codec.getOutputFormat());
119 | } else {
120 | Log.e(TAG, "Failed decoding: " + outputBufferId);
121 | return -1;
122 | }
123 | }
124 | }
125 | }
126 |
127 | @Override
128 | public void seek(int positionMs) {
129 | extractor.seekTo(TimeUnit.MILLISECONDS.toMicros(positionMs), MediaExtractor.SEEK_TO_CLOSEST_SYNC);
130 | }
131 |
132 | @Override
133 | public void close() throws IOException {
134 | synchronized (closeLock) {
135 | codec.release();
136 | extractor.release();
137 | super.close();
138 | }
139 | }
140 |
141 | @Override
142 | public int time() {
143 | return (int) presentationTime;
144 | }
145 | }
--------------------------------------------------------------------------------
/librespot-android-sink/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/librespot-android-sink/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'maven-publish'
4 | }
5 |
6 | android {
7 | compileSdkVersion 31
8 | buildToolsVersion "30.0.3"
9 |
10 | defaultConfig {
11 | minSdkVersion 23
12 | targetSdkVersion 31
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | consumerProguardFiles "consumer-rules.pro"
17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | compileOptions {
27 | sourceCompatibility JavaVersion.VERSION_1_8
28 | targetCompatibility JavaVersion.VERSION_1_8
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation 'xyz.gianlu.librespot:librespot-sink-api:1.6.2'
34 |
35 | testImplementation 'junit:junit:4.13.2'
36 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
37 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
38 | }
--------------------------------------------------------------------------------
/librespot-android-sink/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devgianlu/librespot-android/78602aeb2ea174b1e074e5ea3c378143144d51da/librespot-android-sink/consumer-rules.pro
--------------------------------------------------------------------------------
/librespot-android-sink/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
--------------------------------------------------------------------------------
/librespot-android-sink/src/androidTest/java/xyz/gianlu/librespot/android/sink/AudioStreamInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android.sink;
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import java.io.IOException;
9 |
10 | import xyz.gianlu.librespot.player.mixing.output.OutputAudioFormat;
11 | import xyz.gianlu.librespot.player.mixing.output.SinkException;
12 |
13 | import static android.media.AudioTrack.PLAYSTATE_PLAYING;
14 | import static java.util.stream.IntStream.range;
15 | import static org.junit.Assert.assertEquals;
16 | import static xyz.gianlu.librespot.android.sink.ToneGenerator.genTone;
17 |
18 | @RunWith(AndroidJUnit4.class)
19 | public class AudioStreamInstrumentedTest {
20 |
21 | @Test
22 | public void testActualBeep() throws SinkException {
23 |
24 | // given
25 | AndroidSinkOutput codeUnderTest = new AndroidSinkOutput();
26 | OutputAudioFormat outputAudioFormat = new OutputAudioFormat(
27 | 44100,
28 | 16,
29 | 1,
30 | true,
31 | false
32 | );
33 | int durationInSeconds = 2;
34 |
35 | // when
36 | codeUnderTest.start(outputAudioFormat);
37 | range(0, durationInSeconds).forEach(value -> {
38 | byte[] generatedSnd = genTone(1, (int) outputAudioFormat.getSampleRate(), 400);
39 |
40 | try {
41 | codeUnderTest.write(generatedSnd, 0, generatedSnd.length);
42 | } catch (IOException e) {
43 | e.printStackTrace();
44 | }
45 | });
46 |
47 | // then
48 | assertEquals(PLAYSTATE_PLAYING, codeUnderTest.getPlayState());
49 | // Manual Assertion: You should hear a beep on the device/emulator
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/librespot-android-sink/src/androidTest/java/xyz/gianlu/librespot/android/sink/ToneGenerator.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android.sink;
2 |
3 | /* From: https://stackoverflow.com/a/33676423
4 | * Author: https://stackoverflow.com/users/3896025/gerry
5 | * License: https://creativecommons.org/licenses/by-sa/3.0/
6 | */
7 | class ToneGenerator {
8 |
9 | //Generate tone data for 1 seconds
10 | static byte[] genTone(int iStep, int sampleRate, int m_ifreq) {
11 | double[] sample = new double[sampleRate];
12 |
13 | for (int i = 0; i < sampleRate; ++i) {
14 | sample[i] = Math.sin(2 * Math.PI * (i + iStep * sampleRate) / (sampleRate / m_ifreq));
15 | }
16 |
17 | // convert to 16 bit pcm sound array
18 | // assumes the sample buffer is normalised.
19 | byte[] generatedSnd = new byte[2 * sampleRate];
20 | int idx = 0;
21 | for (final double dVal : sample) {
22 | // scale to maximum amplitude
23 | final short val = (short) ((dVal * 32767));
24 | // in 16 bit wav PCM, first byte is the low order byte
25 | generatedSnd[idx++] = (byte) (val & 0x00ff);
26 | generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
27 | }
28 | return generatedSnd;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/librespot-android-sink/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/librespot-android-sink/src/main/java/xyz/gianlu/librespot/android/sink/AndroidSinkOutput.java:
--------------------------------------------------------------------------------
1 | package xyz.gianlu.librespot.android.sink;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.AudioTrack;
5 |
6 | import org.jetbrains.annotations.NotNull;
7 | import org.jetbrains.annotations.Range;
8 | import org.jetbrains.annotations.VisibleForTesting;
9 |
10 | import java.io.IOException;
11 |
12 | import xyz.gianlu.librespot.player.mixing.output.OutputAudioFormat;
13 | import xyz.gianlu.librespot.player.mixing.output.SinkException;
14 | import xyz.gianlu.librespot.player.mixing.output.SinkOutput;
15 |
16 | import static android.media.AudioFormat.CHANNEL_OUT_MONO;
17 | import static android.media.AudioFormat.CHANNEL_OUT_STEREO;
18 | import static android.media.AudioFormat.ENCODING_PCM_16BIT;
19 |
20 | /**
21 | * @author devgianlu
22 | */
23 | public final class AndroidSinkOutput implements SinkOutput {
24 | private AudioTrack track;
25 | private float lastVolume = -1;
26 |
27 | @Override
28 | public boolean start(@NotNull OutputAudioFormat format) throws SinkException {
29 | if (format.getSampleSizeInBits() != 16) {
30 | throw new SinkException("Unsupported SampleSize", null);
31 | }
32 | if (format.getChannels() < 1 || format.getChannels() > 2) {
33 | throw new SinkException("Unsupported Number of Channels", null);
34 | }
35 | int pcmEncoding = ENCODING_PCM_16BIT;
36 | int channelConfig = format.getChannels() == 1 ? CHANNEL_OUT_MONO : CHANNEL_OUT_STEREO;
37 | int sampleRate = (int) format.getSampleRate();
38 | int minBufferSize = AudioTrack.getMinBufferSize(
39 | sampleRate,
40 | channelConfig,
41 | pcmEncoding
42 | );
43 |
44 | AudioFormat audioFormat = new AudioFormat.Builder()
45 | .setEncoding(pcmEncoding)
46 | .setSampleRate(sampleRate)
47 | .build();
48 |
49 | try {
50 | track = new AudioTrack.Builder()
51 | .setBufferSizeInBytes(minBufferSize)
52 | .setAudioFormat(audioFormat)
53 | .setTransferMode(AudioTrack.MODE_STREAM)
54 | .build();
55 | } catch (UnsupportedOperationException e) {
56 | throw new SinkException("AudioTrack creation failed in Sink: ", e.getCause());
57 | }
58 |
59 | if (lastVolume != -1) track.setVolume(lastVolume);
60 |
61 | track.play();
62 | return true;
63 | }
64 |
65 | @Override
66 | public void write(byte[] buffer, int offset, int len) throws IOException {
67 | int outcome = track.write(buffer, offset, len, AudioTrack.WRITE_BLOCKING);
68 | switch (outcome) {
69 | case AudioTrack.ERROR:
70 | throw new IOException("Generic Operation Failure while writing Track");
71 | case AudioTrack.ERROR_BAD_VALUE:
72 | throw new IOException("Invalid value used while writing Track");
73 | case AudioTrack.ERROR_DEAD_OBJECT:
74 | throw new IOException("Track Object has died in the meantime");
75 | case AudioTrack.ERROR_INVALID_OPERATION:
76 | throw new IOException("Failure due to improper use of Track Object methods");
77 | }
78 | }
79 |
80 | @Override
81 | public void flush() {
82 | if (track != null) track.flush();
83 | }
84 |
85 | @Override
86 | public boolean setVolume(@Range(from = 0L, to = 1L) float volume) {
87 | lastVolume = volume;
88 | if (track != null) track.setVolume(volume);
89 | return true;
90 | }
91 |
92 | @Override
93 | public void release() {
94 | if (track != null) track.release();
95 | }
96 |
97 | @Override
98 | public void stop() {
99 | if (track != null && track.getPlayState() != AudioTrack.PLAYSTATE_STOPPED) track.stop();
100 | }
101 |
102 | @Override
103 | public void close() {
104 | track = null;
105 | }
106 |
107 | @VisibleForTesting
108 | int getPlayState() {
109 | return track.getPlayState();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':librespot-android-decoder'
2 | include ':librespot-android-decoder-tremolo'
3 | include ':librespot-android-sink'
4 | include ':app'
5 | rootProject.name = "librespot-android"
--------------------------------------------------------------------------------