Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ALSA] wrong volume when starting playback #570

Closed
computer007 opened this issue Apr 21, 2014 · 6 comments
Closed

[ALSA] wrong volume when starting playback #570

computer007 opened this issue Apr 21, 2014 · 6 comments

Comments

@computer007
Copy link

When I set the global system volume with alsa-lib before running VLC or mpg123, the level is properly modified when looking at alsamixer, but the playback starts with a very high volume, ignoring the one configured with alsa-lib. Once playback has started, calling again alsa-lib to set the volume properly modifies the volume and the displayed volume level (alsamixer).

OS: raspbian
Kernel 3.10.36+ #665 PREEMPT
firmware updated with "rpi-update"
pulse-audio not installled, only ALSA

Result of "modinfo" command:

pi@rasp /home/pi/ $ modinfo snd_bcm2835
filename:       /lib/modules/3.10.36+/kernel/sound/arm/snd-bcm2835.ko
alias:          platform:bcm2835_alsa license:        GPL description:
Alsa driver for BCM2835 chip author:         Dom Cobley srcversion:   
0D8794C6E1A26AEFC7F8534 depends:        snd-pcm,snd intree:         Y
vermagic:       3.10.36+ preempt mod_unload modversions ARMv6 parm:   
force_bulk:Force use of vchiq bulk for audio (bool)

To reproduce the bug with raspbian:

  1. install ALSA headers with: "sudo apt-get install libasound2-dev"
  2. have VLC installed (should be the case by default, otherwise "sudo apt-get install vlc")
  3. configure ALSA in order it outputs the sound on the jack: "sudo amixer cset numid=3 1 (1 is the jack output)"
  4. compile my source code (provided below with makefile) with a simple "make"
  5. open 2 SSH consoles in order to monitor the volume level while running the demo code
  6. run "alsamixer" in the firt one and set the volume to 100% (in a second attempt you can set it to 10 percents to view that the volume is also ignored whatever the value). Keep alsamixer opened.
  7. in the second console, run the compiled program: "./ALSA_test"

Here is what I experience:

  1. the volume level moves to 20% in alsamixer (ordered by the call to alsa-lib in the program)
  2. VLC starts the playback (french webradio ;)) with a very high volume (the problem is here, whatever the audio source)
  3. After 1 minute, the program sets the volume to 21% (you can see that with alsamixer), and the volume becomes low (here the real volume level has been applied)

Here is the code "test-alsa-vlc.c":

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <signal.h>
#include <pthread.h>
#include <thread>
#include <alsa/asoundlib.h>
#include <cstdint>

// Prototypes
int run_VLC();
void set_alsa_volume(long vol);

// Main function
int main(int argc, const char* argv[])
{
    // Set the initial volume
    set_alsa_volume(-3837); // 20% in alsamixer

    pid_t child_pid = -1;

    // Fork to run VLC in a child process
    if ( (child_pid=fork()) == -1) {
        perror("An error occured during fork");
        exit(EXIT_FAILURE);

    } else if ( child_pid == 0 ) { // Child process
        // Run VLC
        run_VLC();

    } else { // Parent process  
        sleep(60); // Wait for 1 minute

        // Set a volume level higher than the previous
        set_alsa_volume(-3706); // 21% in alsamixer

        sleep(60); // Wait for 1 minute

        // Kill VLC
        if (child_pid != -1) {
            kill(child_pid, SIGTERM);
        }
    }
    return EXIT_SUCCESS;
}

void set_alsa_volume(long vol)
{
    snd_mixer_t *m_handle;
    snd_mixer_elem_t* m_elem;

    // Open an empty mixer
    if (snd_mixer_open(&(m_handle), SND_MIXER_ELEM_SIMPLE) < 0) {
        printf("Error snd_mixer_open");
        return;
    }

    if (snd_mixer_attach(m_handle, "hw:0") < 0) {
        printf("Error snd_mixer_attach");
        return;
    }

    if (snd_mixer_selem_register(m_handle, NULL, NULL) < 0) {
        printf("Error snd_mixer_selem_register");
        return;
    }

    // Load the mixer elements
    if (snd_mixer_load(m_handle) < 0) {
        printf("Error snd_mixer_load");
        return;
    }

    snd_mixer_selem_id_t *simpleElemId; 
    snd_mixer_selem_id_alloca(&simpleElemId);
    snd_mixer_selem_id_set_index(simpleElemId, 0);
    snd_mixer_selem_id_set_name(simpleElemId, "PCM");

    m_elem = snd_mixer_find_selem(m_handle, simpleElemId);
    if (m_elem == NULL) {
        printf("Error snd_mixer_find_selem");
        return;
    }

    // Set the volume
    if (snd_mixer_selem_set_playback_volume_all(m_elem, vol) == 0) {
        std::cout << "ALSA volume level set to " << vol << std::endl;
    }
}


int run_VLC()
{
    // Build the array of arguments
    char * arguments[4] = { "cvlc",
                             "-vvv", // Verbose mode
                             "http://streaming.radio.funradio.fr/fun-1-44-128",
                              NULL
                              };

    if ( execv("/usr/bin/cvlc", const_cast<char * const *>(arguments)) == -1 ) {
        // Should never be printed if execv() is properly executed
        perror("Error in execv() when trying to run VLC");
    }

    return EXIT_FAILURE;
}

And the "makefile":

# Compiler to use for C++
CC=g++

CFLAGS=-std=c++0x

LIBRARY=-lasound

all: test-alsa-vlc.o
    $(CC) $(CFLAGS) $(LIBRARY) -o ALSA_test $^

test-alsa-vlc.o: test-alsa-vlc.c
    $(CC) $(CFLAGS) -c $< -o $@

In the case where it works when launching for the first time, try rebooting, and the bug should occur.

If you need more info, just ask!

Thank you

@Jeoffreybauvin
Copy link

Same issue here, with my Raspberry Pi model B, and a fresh new Raspbian ;).

@popcornmix
Copy link
Collaborator

@computer007
Thanks for the detailed bug report.
I think I have a fix. I'll push it in next firmware update, but if you want to test try:
https://dl.dropboxusercontent.com/u/3669512/temp/start_alsavol.elf

This is a fixed 256M/256M arm/gpu memory split test build. Replace your current start.elf file with it.

@popcornmix
Copy link
Collaborator

Now in latest rpi-update firmware. Please test.

popcornmix pushed a commit to raspberrypi/firmware that referenced this issue Apr 27, 2014
kernel: config: Add CONFIG_NFS_SWAP
See: #266

firmware: alsa: fix for wrong volume when starting playback
See: raspberrypi/linux#570

firmware: Support passthrough through alsa with channels=0
See: raspberrypi/linux#528
popcornmix pushed a commit to Hexxeh/rpi-firmware that referenced this issue Apr 27, 2014
kernel: config: Add CONFIG_NFS_SWAP
See: raspberrypi/firmware#266

firmware: alsa: fix for wrong volume when starting playback
See: raspberrypi/linux#570

firmware: Support passthrough through alsa with channels=0
See: raspberrypi/linux#528
@computer007
Copy link
Author

@popcornmix Thank you. I just tried it, and it seems to have solved the bug. I will confirm it after further tests by the end of the week :)

PS: By curiosity, what caused the bug. I had a look at this file https://github.com/raspberrypi/linux/blob/rpi-patches/sound/arm/bcm2835.c, but I did not notice something special.

@popcornmix
Copy link
Collaborator

The fix was done on the firmware side.
Basically a volume change occurring before the channel was started was lost (subsequent ones would work okay).

@computer007
Copy link
Author

Hello,
After further tests I can say that it solved the issue. Thank you again!

cpinkham added a commit to FalconChristmas/fpp that referenced this issue Jun 4, 2014
- Add a work-around for audio issues in older Raspberry firmware.
  raspberrypi/linux#570

- Move a few things around to give DHCP a little more time to come
  up before we log/announce the IP addresses.  This way we're doing
  something rather than just waiting in WaitForDHCPIPs for the IP(s)
  to come up.

- Disable wifi interface by default on stock SD image so that
  WaitForDHCPIPs doesn't wait 60 seconds for it to get an IP address.
  When users configure wifi via the Network Config screen, we'll
  detect that and wait for an IP to come up on the wireless interface.

- Execute flite in the background so that we can proceed with bootup
  while it announces our IP addresses.  Shaves another few seconds off
  our boot time.
neuschaefer pushed a commit to neuschaefer/raspi-binary-firmware that referenced this issue Feb 27, 2017
kernel: config: Add CONFIG_NFS_SWAP
See: raspberrypi#266

firmware: alsa: fix for wrong volume when starting playback
See: raspberrypi/linux#570

firmware: Support passthrough through alsa with channels=0
See: raspberrypi/linux#528
anholt pushed a commit to anholt/linux that referenced this issue Oct 6, 2017
do_xdp_generic must be called inside rcu critical section with preempt
disabled to ensure BPF programs are valid and per-cpu variables used
for redirect operations are consistent. This patch ensures this is true
and fixes the splat below.

The netif_receive_skb_internal() code path is now broken into two rcu
critical sections. I decided it was better to limit the preempt_enable/disable
block to just the xdp static key portion and the fallout is more
rcu_read_lock/unlock calls. Seems like the best option to me.

[  607.596901] =============================
[  607.596906] WARNING: suspicious RCU usage
[  607.596912] 4.13.0-rc4+ raspberrypi#570 Not tainted
[  607.596917] -----------------------------
[  607.596923] net/core/dev.c:3948 suspicious rcu_dereference_check() usage!
[  607.596927]
[  607.596927] other info that might help us debug this:
[  607.596927]
[  607.596933]
[  607.596933] rcu_scheduler_active = 2, debug_locks = 1
[  607.596938] 2 locks held by pool/14624:
[  607.596943]  #0:  (rcu_read_lock_bh){......}, at: [<ffffffff95445ffd>] ip_finish_output2+0x14d/0x890
[  607.596973]  #1:  (rcu_read_lock_bh){......}, at: [<ffffffff953c8e3a>] __dev_queue_xmit+0x14a/0xfd0
[  607.597000]
[  607.597000] stack backtrace:
[  607.597006] CPU: 5 PID: 14624 Comm: pool Not tainted 4.13.0-rc4+ raspberrypi#570
[  607.597011] Hardware name: Dell Inc. Precision Tower 5810/0HHV7N, BIOS A17 03/01/2017
[  607.597016] Call Trace:
[  607.597027]  dump_stack+0x67/0x92
[  607.597040]  lockdep_rcu_suspicious+0xdd/0x110
[  607.597054]  do_xdp_generic+0x313/0xa50
[  607.597068]  ? time_hardirqs_on+0x5b/0x150
[  607.597076]  ? mark_held_locks+0x6b/0xc0
[  607.597088]  ? netdev_pick_tx+0x150/0x150
[  607.597117]  netif_rx_internal+0x205/0x3f0
[  607.597127]  ? do_xdp_generic+0xa50/0xa50
[  607.597144]  ? lock_downgrade+0x2b0/0x2b0
[  607.597158]  ? __lock_is_held+0x93/0x100
[  607.597187]  netif_rx+0x119/0x190
[  607.597202]  loopback_xmit+0xfd/0x1b0
[  607.597214]  dev_hard_start_xmit+0x127/0x4e0

Fixes: d445516 ("net: xdp: support xdp generic on virtual devices")
Fixes: b5cdae3 ("net: Generic XDP")
Acked-by: Daniel Borkmann <[email protected]>
Signed-off-by: John Fastabend <[email protected]>
Acked-by: Alexei Starovoitov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
cpinkham added a commit to FalconChristmas/fpp that referenced this issue Mar 9, 2018
…rage

We no longer need the workaround for the volume adjustment at boot.  The
firmware issue was fixed a long time ago as referenced in
raspberrypi/linux#570

When using a NFS share for /home/fpp/media, the storage source location
was not getting parsed properly due to the length of the field, so change
the parsing of the findmnt output a little to handle this case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants