All of lore.kernel.org
 help / color / mirror / Atom feed
From: GitHub issues - opened <github@alsa-project.org>
To: alsa-devel@alsa-project.org
Subject: Problems with "snd_pcm_hw_params_set_rate_near" and "snd_pcm_hw_params_set_period_size_near" in x86_64 assembly.
Date: Fri,  8 Aug 2025 21:47:03 +0200 (CEST)	[thread overview]
Message-ID: <1859e25d6dd84900-webhooks-bot@alsa-project.org> (raw)
In-Reply-To: <1859e25d6d7e8300-webhooks-bot@alsa-project.org>

alsa-project/alsa-lib issue #471 was opened from sc1ntilla:

### **PREAMBLE:**

I have never worked with any sound system before, so I'm almost sure that it's just me doing something wrong, but I can't see what, so I'm asking for help.

I'm doing this project for fun, and to learn a lot of stuff, so feel free to give your opinions / advice if you want to.

### **WHAT HAPPENS:**

When calling `snd_pcm_hw_params_set_rate_near` and `snd_pcm_hw_params_set_period_size_near` memory protection violation is issued.
I find that strange, because `snd_pcm_hw_params_set_buffer_size_near` works perfectly fine, and it's similiar to these two.

### **WHAT I TRIED:**
- Making sure that stack after call is on address divisible by 96 (by adding 8 to stack pointer),
- Making sure that `*val` argument is on address divisible by 96,
- Misaligning stack by 8, 16, 24 and 32 before calling these functions (by subtracting from stack pointer),
- Providing 0 to `*val` argument, to rule out that writing to output crashes,
- Providing valid output address to `*dir` argument to rule out that 0 is causing crashes,
- Calling these functions in different order,
- Trying to call `snd_pcm_set_params` instead, but it says _"Channels count (0) not available for PLAYBACK: Invalid argument"_ however, I'm sure that I provided a valid number (2). I even hardcoded it.

But to no avail. Is it my misunderstanding of how alsa-lib works? Very likely. Is my assembly code faulty? Quite possible. I just can't see where the problem lies. If you see error somewhere, please let me know.

### **ADDITIONAL INFORMATION:**

I have multiple audio outputs: monitors with built-in speakers, standalone speakers, and analog jack headphones. 
I hardcoded `hw:2,0` as device name to open. Sometimes it results in `snd_pcm_open` returning _"File descriptor in bad state"_.
When I tried using `sysdefault` it often returns _"ALSA lib /var/tmp/portage/media-libs/alsa-lib-1.2.14/work/alsa-lib-1.2.14/src/pcm/pcm_dmix.c:1000:(snd_pcm_dmix_open) unable to open slave"_



Below is .data section in which globals are stored, and source of function that will be used to play audio buffers.

.data section:

```
.section .data
.align 32

  test2: .8byte 0
  test:  .8byte 0

  SND_PCM_NONBLOCK:                .8byte 0x1
  SND_PCM_ASYNC:                   .8byte 0x2
  SND_PCM_STREAM_PLAYBACK:         .8byte 0

  SND_PCM_FORMAT_U8:               .8byte 1
  SND_PCM_FORMAT_U16_LE:           .8byte 4
  SND_PCM_FORMAT_U24_LE:           .8byte 8
  SND_PCM_FORMAT_U32_LE:           .8byte 12
  SND_PCM_FORMAT_S8:               .8byte 0
  SND_PCM_FORMAT_S16_LE:           .8byte 2
  SND_PCM_FORMAT_S24_LE:           .8byte 6
  SND_PCM_FORMAT_S32_LE:           .8byte 10

  SND_PCM_ACCESS_MMAP_INTERLEAVED: .8byte 0
  SND_PCM_STATE_PREPARED:          .8byte 2

  AUDIO_BUFFER_STATE_IDLE:         .8byte 0
  AUDIO_BUFFER_STATE_WRITING:      .8byte 1
  AUDIO_BUFFER_STATE_PLAYING:      .8byte 2

  t1: .8byte 0
  t2: .8byte 0

  alsa:
    alsa.pcm_handle:   .8byte 0
    alsa.hw_params:    .8byte 0
    alsa.last_error:   .8byte 0
    alsa.initialized:  .8byte 0
    alsa.device_name:  .ascii "hw:2,0\0"

  audio_buffers.count_max: .8byte 16

  amd64_audio_last_error: .8byte 0
```

function: 

```
  amd64_audio_play:

    /* rdi: (input) address to audio data:
     *        (+0/2) audio format (1: PCM, 2: IEEE754)
     *        (+2/2) amount of channels
     *        (+4/4) rate in hertz
     *        (+8/4) bytes per sec (frequency * bytes per block)
     *        (+12/2) bytes per block (number of channels * bits per sample / 8)
     *        (+14/2) bits per sample
     *        (+16/8) total size of samples data
     *        (+24/8) address to samples data
    */


    /* Align stack on 96byte boundary: */

    push %r15
    mov %rsp,  %r15
    and $-32,  %rsp

    mov %rsp, %rax
    mov  $96, %r14
    xor %rdx, %rdx
    div %r14
    sub %rdx, %rsp

    sub $96, %rsp
    mov %r15, (%rsp)


    /* Store registers: */

    sub $192, %rsp
    call amd64_util_store_gpr_regs


    /* Create stack space: */

    sub $192, %rsp
    mov %rdi, (%rsp)

    /* stack layout:
     *   (+0/8) rdi (address to audio data)
     *   (+8/8) buffer size (altered by *buffer_size_near)
     *   (+16/8) period size (set when setting period size)
     *   (+24/8) rate in hertz
     *   (+32/8) temp
    */


    xor %r15, %r15
    mov 16(%rdi), %r15
    mov %r15, 8(%rsp)

    xor %r15, %r15
    mov 4(%rdi), %r15d
    mov %r15d, 24(%rsp)

    movq $0, 32(%rsp)


    /* Open pcm if needed: */

    cmpq $0, (alsa.pcm_handle)
    jne .amd64_audio_play.pcm_is_open

      lea alsa.pcm_handle,  %rdi
      mov %rdi, (%rdi)
      lea alsa.device_name, %rsi
      mov (SND_PCM_ACCESS_MMAP_INTERLEAVED), %rdx
      mov (SND_PCM_NONBLOCK), %r10

      call snd_pcm_open

      cmp $0, %rax
      jne .amd64_audio_play.error.snd_pcm_open

    .amd64_audio_play.pcm_is_open:


    /* Allocate hw params: */

    cmpq $0, (alsa.hw_params)
    jne .amd64_audio_play.hw_params_are_allocated

      lea alsa.hw_params, %rdi
      mov %rdi, (%rdi)

      call snd_pcm_hw_params_malloc

      cmp $0, %rax
      jne .amd64_audio_play.error.snd_pcm_hw_params_malloc

    .amd64_audio_play.hw_params_are_allocated:


    /* Get all possible combinations into hw params: */

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi

    call snd_pcm_hw_params_any

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_any


    /* Set access: */

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi
    mov (SND_PCM_ACCESS_MMAP_INTERLEAVED), %rdx

    call snd_pcm_hw_params_set_access

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_set_access


    /* Set format: */

    xor %rdi, %rdi
    mov (%rsp), %rdi
    mov 14(%rdi), %r15w
    mov (%rdi), %r14w

    cmp $1, %r14w
    jne .amd64_audio_play.error.format_unsupported

    cmpw $32, %r15w
    je .amd64_audio_play.format32
    cmpw $24, %r15w
    je .amd64_audio_play.format24
    cmpw $16, %r15w
    je .amd64_audio_play.format16
    cmpw  $8, %r15w
    je .amd64_audio_play.format8
    jmp .amd64_audio_play.error.format_unsupported

    .amd64_audio_play.format32:
      mov (SND_PCM_FORMAT_S32_LE), %rdx
      jmp .amd64_audio_play.format_end

    .amd64_audio_play.format24:
      mov (SND_PCM_FORMAT_S24_LE), %rdx
      jmp .amd64_audio_play.format_end

    .amd64_audio_play.format16:
      mov (SND_PCM_FORMAT_S16_LE), %rdx
      jmp .amd64_audio_play.format_end

    .amd64_audio_play.format8:
      mov (SND_PCM_FORMAT_S8), %rdx
      jmp .amd64_audio_play.format_end

    .amd64_audio_play.format_end:

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi

    call snd_pcm_hw_params_set_format

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_set_format


    /* Set channels: */

    xor %rdx, %rdx
    mov (%rsp), %r15

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi
    mov 2(%r15), %dx

    call snd_pcm_hw_params_set_channels

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_set_channels


    /* Set buffer size near: */    /* Returns 0, meaning it succeeded. No crashes generated. */

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi
    mov %rsp, %rdx
    add   $8, %rdx
    mov   $0, %r10

    call snd_pcm_hw_params_set_buffer_size_near

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_set_buffer_size_near


    /* Set rate near: */   /* CRASHES */

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi
    mov %rsp, %rdx
    add  $24, %rdx
    mov   $0, %r10

    call snd_pcm_hw_params_set_rate_near

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_set_rate_near


    /* Set period size near: */  /* CRASHES */

    mov 8(%rsp), %rax
    mov $4, %r15
    xor %rdx, %rdx
    div %r15
    mov %rax, 16(%rsp)

    mov (alsa.pcm_handle), %rdi
    mov (alsa.hw_params), %rsi
    mov %rsp, %rdx
    add  $16, %rdx
    mov   $0, %r10

    call snd_pcm_hw_params_set_period_size_near

    cmp $0, %rax
    jne .amd64_audio_play.error.snd_pcm_hw_params_set_period_size_near








    /* Free hw params: */

    cmpq $0, (alsa.hw_params)
    je .amd64_audio_play.hw_params_not_allocated

      mov (alsa.hw_params), %rdi

      call snd_pcm_hw_params_free

      movq $0, (alsa.hw_params)

    .amd64_audio_play.hw_params_not_allocated:


    /* Register errors: */

    xor %rax, %rax
    jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_open:
      mov %rax, (amd64_audio_last_error)
      mov $-1, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_malloc:
      mov %rax, (amd64_audio_last_error)
      mov $-2, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_any:
      mov %rax, (amd64_audio_last_error)
      mov $-3, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_set_access:
      mov %rax, (amd64_audio_last_error)
      mov $-4, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.format_unsupported:
      mov $-5, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_set_format:
      mov %rax, (amd64_audio_last_error)
      mov $-6, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_set_channels:
      mov %rax, (amd64_audio_last_error)
      mov $-7, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_set_buffer_size_near:
      mov %rax, (amd64_audio_last_error)
      mov $-8, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_set_period_size_near:
      mov %rax, (amd64_audio_last_error)
      mov $-9, %rax
      jmp .amd64_audio_play.exit

    .amd64_audio_play.error.snd_pcm_hw_params_set_rate_near:
      mov %rax, (amd64_audio_last_error)
      mov $-10, %rax
      jmp .amd64_audio_play.exit


    /* Exit: */

    .amd64_audio_play.exit:


    /* Print error to stdout: */

    mov %rax, %rdi
    call amd64_util_print_dec
    call amd64_util_print_newline

    cmpq $0, (amd64_audio_last_error)
    je .amd64_audio_play.no_error

      mov (amd64_audio_last_error), %rdi
      call snd_strerror

      mov %rax, %rdi
      call amd64_util_print2
      call amd64_util_print_newline

    .amd64_audio_play.no_error:


    /* Restore stack: */

    add $192, %rsp


    /* Restore registers without rax: */

    mov %rax, 128(%rsp)
    call amd64_util_restore_gpr_regs
    mov 128(%rsp), %rax
    add $192, %rsp


    /* Restore stack alignment: */

    pop %rsp
    pop %r15

    ret
```

Issue URL     : https://github.com/alsa-project/alsa-lib/issues/471
Repository URL: https://github.com/alsa-project/alsa-lib

           reply	other threads:[~2025-08-08 19:47 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <1859e25d6d7e8300-webhooks-bot@alsa-project.org>]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1859e25d6dd84900-webhooks-bot@alsa-project.org \
    --to=github@alsa-project.org \
    --cc=alsa-devel@alsa-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.