Userland: No sound.

Created on 31 Oct 2018  路  7Comments  路  Source: CypherpunkArmory/UserLAnd

I am using ubuntu with xfce but sounds are not working, videos works fine on youtube on firefox.
I am curious if that is even an issue or just a feature planned for future?

Most helpful comment

To be able to use sound.
The reliable way is to combine Termux project with Userland.
Install Debian or Ubuntu as usual. Install Termux from google Play store.
When you install Termux app
type
pkg install pulseaudio
add to The /etc/profile
The following lines. Place them at The last line of this Bash script
after last fi word. On The last empty line inside this script.
pulseaudio --start --exit-idle-time=-1
pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1
auth-anonymous=1

On yours Userland installed distribution.
Add this as non root user.
echo "export PULSE_SERVER=\"127.0.0.1\"" >> ~/.bashrc
You can install Pulseaudio by typing
sudo apt install pulseaudio
And sound should work.
This approach is also compatible with Xserver XSDL on Google Play, since
Xserver XSDL build in Pulseaudio support do not read this variable.
But please be tolerant. Even this stable approach produces little time
delay. But sound is not distorted and even text to speech synthesizers
work without random crashes.

All 7 comments

To be able to use sound.
The reliable way is to combine Termux project with Userland.
Install Debian or Ubuntu as usual. Install Termux from google Play store.
When you install Termux app
type
pkg install pulseaudio
add to The /etc/profile
The following lines. Place them at The last line of this Bash script
after last fi word. On The last empty line inside this script.
pulseaudio --start --exit-idle-time=-1
pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1
auth-anonymous=1

On yours Userland installed distribution.
Add this as non root user.
echo "export PULSE_SERVER=\"127.0.0.1\"" >> ~/.bashrc
You can install Pulseaudio by typing
sudo apt install pulseaudio
And sound should work.
This approach is also compatible with Xserver XSDL on Google Play, since
Xserver XSDL build in Pulseaudio support do not read this variable.
But please be tolerant. Even this stable approach produces little time
delay. But sound is not distorted and even text to speech synthesizers
work without random crashes.

@JanuszChmiel
Works like a charm for me. Got milkytracker and audacity running on my phone now, feels great.

@JanuszChmiel ,

Thank you for your assistance, we really appreciate it. Getting sound to work seamlessly in UserLAnd is still an ongoing project we are working to address.

@JanuszChmiel ,

I have done everything I mentioned and did not work, it shows me a mistake [E: [pulseaudio] main.c: Too many arguments.]
I do not know what is the reason for this error and the sound does not work

But I do not know if you run the sound over the following command, [export PULSE_SERVER=tcp:127.0.0.1:4712] but it does not work if the xsdl application becomes in the background of the flag I used for Termux and works on Userland also, but Userland is relatively obsolete on the Termux on my phone,

I have used a compiler to reply and can contain errors in sentences that carry me a bit 馃榾馃榾

Thank you ...

For anyone that have the error "too many arguments", just put those 2 on 2 separate lines like this:

pulseaudio --start --exit-idle-time=-1

pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1

I have forgotten one very important think on my previous older post. Instal sox to The Termux environment.
apt install sox
It will not work without this module.
By The way. Termux have modified Pulseaudio so it communicate with Alsa sound system on every Android device without crashes. I Am sending you one .C source code from 2010 year. It is may be much more worst than source variant which is integrated to Termux Pulseaudio package.
I Am sending it to you so somebody of programmers could think about The similar module for Userland. I think, that it would be A good idea to create The separate little repository for Debian and Ubuntu, since it is The most usable Linux distributions. Standard Pulseaudio officially compiled from The desktop.org site will very probably never include official Android sound support out of The box.

Convincing PUlseaudio developers to do that will be very probably non easy way of discussion. Pulseaudio is mainly for standard PCI based computers and for standard Linux, which is not based on restricted userspace variant, where udev do not work.
Here is source code for inspiration. C language experts can download source code for Termux Pulseaudio to compare and may be, that Pulseaudio will be really able to support Android sound.
/*

  • Copyright (C) 2010 The Android Open Source Project
    *
  • Licensed under the Apache License, Version 2.0 (the "License");
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
    *
  • http://www.apache.org/licenses/LICENSE-2.0
    *
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.
    /
    /
    interactive buffer queue test program */

ifdef ANDROID

define USE_ANDROID_SIMPLE_BUFFER_QUEUE // change to #undef for compatibility testing

endif

include

include

include

include

include

include

include

ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE

include

endif

ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE

define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE

define IID_BUFFERQUEUE SL_IID_ANDROIDSIMPLEBUFFERQUEUE

define BufferQueueItf SLAndroidSimpleBufferQueueItf

define BufferQueueState SLAndroidSimpleBufferQueueState

define IID_BUFFERQUEUE_USED SL_IID_ANDROIDSIMPLEBUFFERQUEUE

define INDEX index

else

define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_BUFFERQUEUE

define IID_BUFFERQUEUE SL_IID_BUFFERQUEUE

define BufferQueueItf SLBufferQueueItf

define BufferQueueState SLBufferQueueState

define IID_BUFFERQUEUE_USED IID_BUFFERQUEUE

define INDEX playIndex

endif

#define checkResult(r) do { \
if ((r) != SL_RESULT_SUCCESS) { \
if ((r) == SL_RESULT_PARAMETER_INVALID) fprintf(stderr, "error SL_RESULT_PARAMETER_INVALID at %s:%d\n", __FILE__, __LINE__); \
else if ((r) == SL_RESULT_PRECONDITIONS_VIOLATED ) fprintf(stderr, "error SL_RESULT_PRECONDITIONS_VIOLATED at %s:%d\n", __FILE__, __LINE__); \
else fprintf(stderr, "error %d at %s:%d\n", (int) r, __FILE__, __LINE__); \
} \
} while (0)
typedef struct {
short left;
short right;
} frame_t;

define SINE_FRAMES (44100*5)

frame_t sine[SINE_FRAMES];
BufferQueueItf expectedCaller = NULL;
void *expectedContext = NULL;

BufferQueueItf playerBufferqueue;
struct pollfd pipeFdInfo;

static void callback(BufferQueueItf caller, void *context)
{
putchar('.');
if (caller != expectedCaller)
printf("caller %p expected %p\r\n", caller, expectedCaller);
if (context != expectedContext)
printf("context %p expected %p\r\n", context, expectedContext);
fflush(stdout);
}

define MAX_BUFF_SIZE 4096

frame_t buff[MAX_BUFF_SIZE];
void piperead() {
int playtime,ret,len,result;
ret = poll(&pipeFdInfo,1,-1);
if (ret < 0) printf("\n error reading pulseaudio pipe \n");

if ( ((pipeFdInfo.revents&POLLIN) == POLLIN) || ((pipeFdInfo.revents&POLLPRI) == POLLPRI) ){
    len = read(pipeFdInfo.fd, buff, sizeof(buff));
    if (len > 0) result = (*playerBufferqueue)->Enqueue(playerBufferqueue, buff, len);
}

}

// this callback handler is called every time a buffer finishes playing
void bqPlayerCallback(BufferQueueItf bq, void *context){
piperead();
}

int main(int argc, char **argv)
{
if (argc != 2) {
printf("usage: %s \n", argv[0]);
exit(1);
}

SLresult result;
// create engine
SLObjectItf engineObject;
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); checkResult(result);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); checkResult(result);
SLEngineItf engineEngine;
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); checkResult(result);
// create output mix
SLObjectItf outputmixObject;
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputmixObject, 0, NULL, NULL);  checkResult(result);
result = (*outputmixObject)->Realize(outputmixObject, SL_BOOLEAN_FALSE); checkResult(result);
// create audio player
SLDataSource audiosrc;
SLDataSink audiosnk;
SLDataLocator_OutputMix locator_outputmix;
SLDataLocator_BufferQueue locator_bufferqueue;
locator_bufferqueue.locatorType = DATALOCATOR_BUFFERQUEUE;
locator_bufferqueue.numBuffers = 1;
locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
locator_outputmix.outputMix = outputmixObject;
SLDataFormat_PCM pcm;
pcm.formatType = SL_DATAFORMAT_PCM;
pcm.numChannels = 2;
pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
pcm.containerSize = 16;
pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
audiosrc.pLocator = &locator_bufferqueue;
audiosrc.pFormat = &pcm;
audiosnk.pLocator = &locator_outputmix;
audiosnk.pFormat = NULL;
SLObjectItf playerObject;
SLInterfaceID ids[1] = {IID_BUFFERQUEUE};
SLboolean flags[1] = {SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audiosrc, &audiosnk,
        1, ids, flags);  checkResult(result);
result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); checkResult(result);
SLPlayItf playerPlay;
result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); checkResult(result);
result = (*playerObject)->GetInterface(playerObject, IID_BUFFERQUEUE_USED, &playerBufferqueue); checkResult(result);
// register callback on the buffer queue
result = (*playerBufferqueue)->RegisterCallback(playerBufferqueue, bqPlayerCallback, NULL); checkResult(result);

SLuint32 state;
state = SL_PLAYSTATE_PLAYING;
result = (*playerPlay)->SetPlayState(playerPlay, state); checkResult(result);

memset (buff, 0, sizeof(buff));

int fd;
if((fd = open(argv[1], O_RDONLY)) == -1) {
    perror("Error opening pulseaudio pipe");
    exit(1);
}

pipeFdInfo.fd = fd;
pipeFdInfo.events = POLLIN|POLLPRI;

printf("start reading pipe...\n");
piperead();
while(1){
    //It looks like callback is called in differend thread
}

}

Thanks to The following article on The following WEB address, I have been able to use several Android players which are capable to play by using simple protocol.

http://kaytat.com/?page_id=301

It is necessary to also uncomment The # character before The line in The file /etc/pulse/default.pa
which load TCP protocol.
I have tested Pulseaudio which run from Termux bz using Proot and I have run Pulseaudio bz using Debian Buster ARM64 Bit edition. Pulseaudio for Termux have not been run and I have rather removed it to ensure that Pulseaudio for Termux will not interfere with my experiment.
Then from Debian, run normally Pulseaudio by typing as non root user

pulseaudio --start --exit-idle-time=-1 &
Then you can test this sound server by using Simple protocol player.
Some warnings!
PUlseaudio memory allocations will very probably crash if you will try to use default 50 MMS buffer or lover value. So use 70 MMS instead. I have intensively tested this value by using Speech-dispatcher and orca and this process intensively play short audio samples and Pulseaudio must free zero source.
Also uncomment zero source in default.pa so it will work.
Simple protocol player So I Am suggesting you to add this audio service by using Kotlin or Java language to yours app.
PUlse droid do not offer The opportunity to specify Buffer audio lenght. But sound output quality is not good. Some audio samples have higher voice pitch, like if you were used it on casette tape player, whichplay some parts of aduio by A higher faster speed.
Sure, there are other opportunity how to play audio which Pulseaudio will stream to some socket.
You also have opportunity to allow users to specify directly PUlseaudio socket path to some storage place.
Some kernels have issues while short audio data will be play and if Sless or other similar approach will be used.
But do not forget on big but reliable sound playback engine based on no C code Exo Player from GOogle.
Sure, it require many libraries, but it can also play. There are also some Android NDK audio examples. Unfortunately, those C examples will not support Android 4.1.1 for example.
There are also other approach such as Vitamio project, Giraffe player. I hope, that you will find some ,

Was this page helpful?
0 / 5 - 0 ratings