// File: fgheng[P]keysound/src/Play.cc
// Function: play(Mixer*, unsigned short, unsigned short, unsigned int, unsigned short)
void play(Mixer *mixer, uint16_t frame_num, uint16_t channels,
        uint32_t sample_rate, uint16_t bits_per_sample) {

    pa_simple *s;
    pa_sample_spec ss;

    switch (bits_per_sample) {
        case 8:
            ss.format = PA_SAMPLE_U8;
            break;
        case 16:
            // wav的数据是小字端存储的		The data of wav is stored in small samples
            ss.format = PA_SAMPLE_S16LE;
            break;
        case 24:
            // 有符号?				Signed?
            ss.format = PA_SAMPLE_S24LE;
            break;
        case 32:
            // 有符号?				Signed?
            ss.format = PA_SAMPLE_S32LE;
            break;
        default:
            ss.format = PA_SAMPLE_INVALID;
            break;
    }
    ss.channels = channels;
    ss.rate = sample_rate;

    s = pa_simple_new(NULL, "keysound", PA_STREAM_PLAYBACK,
                    NULL, "music", &ss, NULL, NULL, NULL);

    if (!s) {
        std::cout << "error occured while connect audio" << std::endl;
        return;
    }

    // 每个frame拥有的字节数		The number of bytes in each frame
    uint16_t frame_bytes = channels * bits_per_sample / 8;
    // 一个buffer持续的时间		The duration of a buffer
    uint32_t sleep_time = (frame_num * frame_bytes * 1000) /
        (sample_rate * channels * bits_per_sample / 8);

    int error, ret;
    uint8_t buf[frame_num * frame_bytes];
    while (!stop) {
        std::memset(buf, 0, frame_num * frame_bytes);
        mixer->get_mix(buf, frame_num * frame_bytes);
        ret = pa_simple_write(s, buf, frame_num * frame_bytes, &error);
        if (ret < 0) {
            std::cout << "pulse write error" << std::endl;
            continue;
        }

        usleep(sleep_time*1000);
    }

    pa_simple_free(s);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movw %r8w, %ax
movq %rdi, -0x8(%rbp)
movw %si, -0xa(%rbp)
movw %dx, -0xc(%rbp)
movl %ecx, -0x10(%rbp)
movw %ax, -0x12(%rbp)
movzwl -0x12(%rbp), %eax
addl $-0x8, %eax
movl %eax, %ecx
movq %rcx, -0x58(%rbp)
subl $0x18, %eax
ja 0xe459
movq -0x58(%rbp), %rax
leaq 0x83ec(%rip), %rcx      # 0x16818
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x0, -0x2c(%rbp)
jmp 0xe460
movl $0x3, -0x2c(%rbp)
jmp 0xe460
movl $0x9, -0x2c(%rbp)
jmp 0xe460
movl $0x7, -0x2c(%rbp)
jmp 0xe460
movl $0xffffffff, -0x2c(%rbp) # imm = 0xFFFFFFFF
movw -0xc(%rbp), %ax
movb %al, -0x24(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0x28(%rbp)
xorl %eax, %eax
movl %eax, %ecx
leaq 0x8404(%rip), %rsi      # 0x1687c
movl $0x1, %edx
leaq 0x8401(%rip), %r8       # 0x16885
leaq -0x2c(%rbp), %r9
subq $0x20, %rsp
movq %rcx, %rdi
movq $0x0, (%rsp)
movq $0x0, 0x8(%rsp)
movq $0x0, 0x10(%rsp)
callq 0x4350
addq $0x20, %rsp
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0xe4e4
movq 0x10af4(%rip), %rdi     # 0x1efb8
leaq 0x83c0(%rip), %rsi      # 0x1688b
callq 0x43a0
movq %rax, %rdi
movq 0x10aae(%rip), %rsi     # 0x1ef88
callq 0x4400
jmp 0xe60c
movzwl -0xc(%rbp), %eax
movzwl -0x12(%rbp), %ecx
imull %ecx, %eax
movl %eax, %ecx
addl $0x7, %ecx
testl %eax, %eax
cmovsl %ecx, %eax
shrl $0x3, %eax
movw %ax, -0x2e(%rbp)
movzwl -0xa(%rbp), %eax
movzwl -0x2e(%rbp), %ecx
imull %ecx, %eax
imull $0x3e8, %eax, %eax      # imm = 0x3E8
movl -0x10(%rbp), %ecx
movzwl -0xc(%rbp), %edx
imull %edx, %ecx
movzwl -0x12(%rbp), %edx
imull %edx, %ecx
shrl $0x3, %ecx
xorl %edx, %edx
divl %ecx
movl %eax, -0x34(%rbp)
movzwl -0xa(%rbp), %eax
movzwl -0x2e(%rbp), %ecx
imull %ecx, %eax
movq %rsp, %rcx
movq %rcx, -0x48(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x60(%rbp)
movq %rcx, %rsp
movq %rax, -0x50(%rbp)
movb 0x13702(%rip), %al      # 0x21c62
xorb $-0x1, %al
testb $0x1, %al
jne 0xe56b
jmp 0xe5fc
movq -0x60(%rbp), %rdi
movzwl -0xa(%rbp), %eax
movzwl -0x2e(%rbp), %ecx
imull %ecx, %eax
movslq %eax, %rdx
xorl %esi, %esi
callq 0x41d0
movq -0x60(%rbp), %rsi
movq -0x8(%rbp), %rdi
movzwl -0xa(%rbp), %edx
movzwl -0x2e(%rbp), %eax
imull %eax, %edx
callq 0xe080
movq -0x60(%rbp), %rsi
movq -0x20(%rbp), %rdi
movzwl -0xa(%rbp), %eax
movzwl -0x2e(%rbp), %ecx
imull %ecx, %eax
movslq %eax, %rdx
leaq -0x38(%rbp), %rcx
callq 0x45c0
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jge 0xe5eb
movq 0x109ed(%rip), %rdi     # 0x1efb8
leaq 0x82db(%rip), %rsi      # 0x168ad
callq 0x43a0
movq %rax, %rdi
movq 0x109a7(%rip), %rsi     # 0x1ef88
callq 0x4400
jmp 0xe55a
imull $0x3e8, -0x34(%rbp), %edi # imm = 0x3E8
callq 0x4500
jmp 0xe55a
movq -0x20(%rbp), %rdi
callq 0x45f0
movq -0x48(%rbp), %rax
movq %rax, %rsp
movq %rbp, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)