Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

Hoping to goodness is not theologically sound. - Peanuts


devel / comp.lang.python / Re: Regarding inability of Python Module Winsound to produce beep in decimal frequency

SubjectAuthor
* Re: Regarding inability of Python Module Winsound to produce beep inEryk Sun
`- Re: Regarding inability of Python Module Winsound to produce beep in decimal freStefan Ram

1
Re: Regarding inability of Python Module Winsound to produce beep in decimal frequency

<mailman.407.1629164596.4164.python-list@python.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=14636&group=comp.lang.python#14636

  copy link   Newsgroups: comp.lang.python
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail
From: eryk...@gmail.com (Eryk Sun)
Newsgroups: comp.lang.python
Subject: Re: Regarding inability of Python Module Winsound to produce beep in
decimal frequency
Date: Mon, 16 Aug 2021 20:43:11 -0500
Lines: 40
Message-ID: <mailman.407.1629164596.4164.python-list@python.org>
References: <CAGnkz7FtQ5krADv6Z67eZFk1Cx+9dA6-FYd39L9jm9aQn33x4g@mail.gmail.com>
<sf644o$14e0$1@ciao.gmane.io>
<CAPTjJmqwz0Rjin9Xj-Lskj8TxUOu=Pxfk2ZgLpkDk7r6z-ef7g@mail.gmail.com>
<396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com>
<20210815130117.03c23726@e7240.home>
<CAPTjJmrJ5D-v_3C3HG2MfvkTFYqWUZtX_cuQ9Mhz=b6qS5QDdw@mail.gmail.com>
<6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net>
<CACL+1atUCiwA9f0zw4WSV-9aoDa3EOjk-C=a90p+--=jg_=T-w@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
X-Trace: news.uni-berlin.de uabDW5ydfrQFQK0AmDqU0A6DDUBpBKehydoj9gc2g85g==
Return-Path: <eryksun@gmail.com>
X-Original-To: python-list@python.org
Delivered-To: python-list@mail.python.org
Authentication-Results: mail.python.org; dkim=pass
reason="2048-bit key; unprotected key"
header.d=gmail.com header.i=@gmail.com header.b=tDwWx0bW;
dkim-adsp=pass; dkim-atps=neutral
X-Spam-Status: OK 0.038
X-Spam-Evidence: '*H*': 0.93; '*S*': 0.00; '(which': 0.04; 'def':
0.04; 'cards': 0.07; 'math': 0.07; 'example:': 0.09; 'roel': 0.09;
'schroeven': 0.09; 'subject:Python': 0.12; 'import': 0.14;
'computers': 0.16; 'generates': 0.16; 'io.bytesio()': 0.16;
'session)': 0.16; 'subject:Module': 0.16; 'subject:frequency':
0.16; 'wrote:': 0.16; 'memory': 0.16; 'speaker': 0.18; 'object':
0.23; 'to:addr:python-list': 0.23; 'task': 0.27; 'it,': 0.31;
'but': 0.31; "i'm": 0.32; 'difference': 0.32;
'received:209.85.214': 0.32; 'message-id:@mail.gmail.com': 0.33;
'header:In-Reply-To:1': 0.33; 'received:google.com': 0.34;
"we're": 0.35; 'necessarily': 0.35; 'yes,': 0.35;
'from:addr:gmail.com': 0.35; 'request': 0.35; 'windows': 0.36;
'received:209.85': 0.38; 'those': 0.38; 'received:209': 0.38;
'does': 0.38; 'could': 0.40; 'skip:w 10': 0.61; 'days': 0.61;
'skip:b 10': 0.62; 'desktop': 0.63; 'skip:m 20': 0.64; 'capable':
0.65; 'talking': 0.65; 'let': 0.65; 'skip:w 20': 0.65; 'yourself':
0.75; 'cycle.': 0.84; 'cycles': 0.84; 'fraction': 0.84;
'redirects': 0.84; 'frequency': 0.91; 'plays': 0.91; 'retained':
0.91; 'subject:Regarding': 0.95
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
h=mime-version:in-reply-to:references:from:date:message-id:subject:to;
bh=gXpsSXZOY3vrTQN9qPKO+sWDKq1v+jni+RE42jHAGx4=;
b=tDwWx0bWrcz9hdBw9RR6GAjvbM38hL0WY647K8M6z++qmX8MmsPZ9Czw1nfUEdzEcG
SVxLlmNaLkyjKSZRBgEYjwZ9ciEefUhh/g0RpBCgq74E/v7SW0CfQb9tWJKAWC/Mz19z
/LERIBkidOGANQtZHFgrBV8LxTTFvxLkhX6iWHDwynZ4czIDzQvokc3jS1ijbnfIPyI+
C3FUokBQZMpQnuw9Nq05Q6CShGFy0APXC6fJwRCkniORriwx5ElU5m4xrwYALKjbgCjt
W49u8VvNY1qRq7DsUPTs8EGSKUU08skdb+b4aoGEmY1gaz5YTirqYI7PVYoYRikp/sEz
EZLw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:mime-version:in-reply-to:references:from:date
:message-id:subject:to;
bh=gXpsSXZOY3vrTQN9qPKO+sWDKq1v+jni+RE42jHAGx4=;
b=RyI+kXdYaa9RubP5cJl5aPb0jwM+APM2JFwbBGyUJf3SbgX44slHXTpYM1x/wb/lXH
WDKJhGvtPXbHeWkEJqvy8NcyqsJXk6KJ5bbW4xmbRMrnQYysOzhK+1nZ5C/nAU2tHeM1
uckhCJic62dUjAIw9mDBv8q/tRXiLVPUFQUH00cOpOp0j+uJY5AncvsOGH+NjtAX41D5
iE3PjPsGDjHdcknjWwGcpagcIp3zbA1NUmX5fGTOaWSenLXgUjDLlNelojPXnx5qcgSB
b9K/aCel81U9DhICM2d+x4kds8mV3pYP9Ky171nOZh6O3ABTrGEULsAiQY99wzxNqVx2
zvIg==
X-Gm-Message-State: AOAM531CcNXKPJoDJJRqhRl/o6/IlwimgoK5NWFipli1EOTAbP8pWhUm
En9tHK19dMjI3/r0xPaXF7LlXOkZ1v/899yQRGIHT5Qw
X-Google-Smtp-Source: ABdhPJzv3s0Xm4myosLq31/vQH3kQvq9cyNTkXxkqyQKLlTQrl5E3Gq5Q7GM+yYLal9DlSMiaSnXzHIY0lGkryjlGnU=
X-Received: by 2002:a63:1e4e:: with SMTP id p14mr978843pgm.261.1629164592008;
Mon, 16 Aug 2021 18:43:12 -0700 (PDT)
In-Reply-To: <6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net>
X-BeenThere: python-list@python.org
X-Mailman-Version: 2.1.34
Precedence: list
List-Id: General discussion list for the Python programming language
<python-list.python.org>
List-Unsubscribe: <https://mail.python.org/mailman/options/python-list>,
<mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive: <https://mail.python.org/pipermail/python-list/>
List-Post: <mailto:python-list@python.org>
List-Help: <mailto:python-list-request@python.org?subject=help>
List-Subscribe: <https://mail.python.org/mailman/listinfo/python-list>,
<mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID: <CACL+1atUCiwA9f0zw4WSV-9aoDa3EOjk-C=a90p+--=jg_=T-w@mail.gmail.com>
X-Mailman-Original-References: <CAGnkz7FtQ5krADv6Z67eZFk1Cx+9dA6-FYd39L9jm9aQn33x4g@mail.gmail.com>
<sf644o$14e0$1@ciao.gmane.io>
<CAPTjJmqwz0Rjin9Xj-Lskj8TxUOu=Pxfk2ZgLpkDk7r6z-ef7g@mail.gmail.com>
<396db396-272b-b7a4-2daf-92e26d005535@mrabarnett.plus.com>
<20210815130117.03c23726@e7240.home>
<CAPTjJmrJ5D-v_3C3HG2MfvkTFYqWUZtX_cuQ9Mhz=b6qS5QDdw@mail.gmail.com>
<6068cc72-6377-458d-0bde-35919f327782@roelschroeven.net>
 by: Eryk Sun - Tue, 17 Aug 2021 01:43 UTC

On 8/16/21, Roel Schroeven <roel@roelschroeven.net> wrote:
>
> We're not necessarily talking about the PC speaker here: (almost) all
> computers these days have sound cards (mostly integrated on the
> motherboard) that are much more capable than those one-bit PC speakers.

Yes, the PC speaker beep does not get used in Windows 7+. The beep
device object is retained for compatibility, but it redirects the
request to a task in the user's session (which could be a remote
desktop session) that generates a WAV buffer in memory and plays it
via PlaySound(). You can do this yourself if you need a more precise
frequency. For example:

import io
import math
import wave
import winsound

def beep(frequency, duration):
'''Play a beep at frequency (hertz) for duration (milliseconds).'''
fs = 48000
f = 2 * math.pi * frequency / fs
n = round(duration * fs / 1000)
b = io.BytesIO()
w = wave.Wave_write(b)
w.setnchannels(1)
w.setsampwidth(2)
w.setframerate(fs)
w.writeframes(b''.join(round(32767 * math.sin(f*i)).to_bytes(
2, 'little', signed=True) for i in range(n)))
w.close()
winsound.PlaySound(b.getbuffer(), winsound.SND_MEMORY)

Play a beep at 277.1826 Hz for one second:

beep(277.1826, 1000)

I'm tone deaf, I suppose, since I need a difference of about 3 cycles
to perceive it, let alone a fraction of a cycle.

Re: Regarding inability of Python Module Winsound to produce beep in decimal frequency

<beep-20220502202348@ram.dialup.fu-berlin.de>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=18117&group=comp.lang.python#18117

  copy link   Newsgroups: comp.lang.python
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail
From: ram...@zedat.fu-berlin.de (Stefan Ram)
Newsgroups: comp.lang.python
Subject: Re: Regarding inability of Python Module Winsound to produce beep in decimal frequency
Date: 2 May 2022 19:36:00 GMT
Organization: Stefan Ram
Lines: 1014
Expires: 1 Apr 2023 11:59:58 GMT
Message-ID: <beep-20220502202348@ram.dialup.fu-berlin.de>
References: <mailman.407.1629164596.4164.python-list@python.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Trace: news.uni-berlin.de 7TNFBvwwyv3wWM58UBS27QeEAWWLAHbd3D8xiJxghxLWMf
X-Copyright: (C) Copyright 2022 Stefan Ram. All rights reserved.
Distribution through any means other than regular usenet
channels is forbidden. It is forbidden to publish this
article in the Web, to change URIs of this article into links,
and to transfer the body without this notice, but quotations
of parts in other Usenet posts are allowed.
X-No-Archive: Yes
Archive: no
X-No-Archive-Readme: "X-No-Archive" is set, because this prevents some
services to mirror the article in the web. But the article may
be kept on a Usenet archive server with only NNTP access.
X-No-Html: yes
Content-Language: en-US
Accept-Language: de-DE, en-US, it, fr-FR
 by: Stefan Ram - Mon, 2 May 2022 19:36 UTC

Eryk Sun <eryksun@gmail.com> writes:
>def beep(frequency, duration):
> '''Play a beep at frequency (hertz) for duration (milliseconds).'''
> fs = 48000
> f = 2 * math.pi * frequency / fs
> n = round(duration * fs / 1000)
> b = io.BytesIO()
> w = wave.Wave_write(b)
> w.setnchannels(1)
> w.setsampwidth(2)
> w.setframerate(fs)
> w.writeframes(b''.join(round(32767 * math.sin(f*i)).to_bytes(
> 2, 'little', signed=True) for i in range(n)))
> w.close()
> winsound.PlaySound(b.getbuffer(), winsound.SND_MEMORY)

Thanks for this very instructive example! I wondered whether
it is possible to play a melody this way and extended your
example. (The program allocates large buffers, which might
lead to problems on systems which do not have more than 1 GB
of main memory.)

To hear some variations, one can first hear it as is, then
try "reverb = False" below and then (keeping "reverb = False")
"instrument = 1" instead of "instrument = 0".

# Plays BWV 846 on Windows
# # requires:
# - Python 3.9
# - winsound (i.e., Windows)

# Created 2021-08/2021-09 # Stefan Ram
# Cleaned up 2021-12/2022-01/2022-05 # Stefan Ram

import io
import math
import wave
import winsound
import random
import array
import sys
import time
from math import sin

anti_click = True
sine = False
hull_curve = True
intro = True
reverb = True
noise = True
randomness_intensities = True
instrument = 0

if noise:
strong_noise = lambda x:( random.random() - 0.5 )* x/2 + x
weak_noise = lambda x:( random.random() - 0.5 )* x/5 + x
else:
strong_noise = lambda x: x
weak_noise = lambda x: x

def initialize_frame_buffer():
estimated_duration_in_seconds = 140
frame_buffer_size = estimated_duration_in_seconds * frames_per_second
global frame_values
frame_values =[ 0 ]* frame_buffer_size
del frame_buffer_size
global write_position
write_position = 0

def initialize_reverb_buffers():
global reverb_buffer_size
reverb_buffer_size = 10000
global reverb_buffer
reverb_buffer =[ 0.0 ]* reverb_buffer_size
global primary_reverb_buffer_position
primary_reverb_buffer_position = 0

global size_of_the_second_reverb_buffer
size_of_the_second_reverb_buffer =22768
global second_reverb_buffer
second_reverb_buffer =[ 0.0 ]*size_of_the_second_reverb_buffer
global second_reverb_buffer_position
second_reverb_buffer_position = 0

def initialize():
global frames_per_second
frames_per_second = 48000

print( "Program might need about 1 GB of main memory.\nPlease "+
"be patient." )

initialize_frame_buffer()
initialize_reverb_buffers()
record_signal_for_reverb( 0 )

global number_of_tones_or_pauses_inserted
number_of_tones_or_pauses_inserted = 0

def record_signal_for_reverb( signal ):
global reverb_buffer_is_initialized
global primary_reverb_buffer_position
global second_reverb_buffer_position
reverb_buffer[ primary_reverb_buffer_position ]= signal
primary_reverb_buffer_position += 1
primary_reverb_buffer_position %= reverb_buffer_size
second_reverb_buffer[ second_reverb_buffer_position ]= signal
second_reverb_buffer_position += 1
second_reverb_buffer_position %= size_of_the_second_reverb_buffer
return signal

def some_reverb():
return reverb_buffer[ primary_reverb_buffer_position ]* 0.3 +\
second_reverb_buffer[ second_reverb_buffer_position ]* 0.1

def free_reverb_buffer_memory():
global reverb_buffer
reverb_buffer = None
del reverb_buffer

global second_reverb_buffer
second_reverb_buffer = None
del second_reverb_buffer

def show_progress():
global number_of_tones_or_pauses_inserted
text = "Please stand by while I'm filling the buffer!"
if number_of_tones_or_pauses_inserted % 20 == 0:
cd = 545 + 69 - number_of_tones_or_pauses_inserted
cdp = int( cd / 620 * 100 )
print( "About "+ str( cdp )+" % to go. " + text )
number_of_tones_or_pauses_inserted += 1

def integral_duration_of( duration ):
"convert from duration in milliseconds to duration in frames"
return round( duration * frames_per_second / 1000 )

def hull_curve_of( frame_number, integral_duration ):
'''
preconditions:
frame_number <= integral_duration
integral_duration > -1
/`-.
ADSR
attack-decay-sustain-release curve
attack: rise to maximum_intensity until end_of_attack,
decay: then fall to 1 until end_of_decay,
sustain: then, sustain the value of 1 until
integral_duration - initial_duration,
release: finally, fall to 0 until integral_duration
'''
initial_duration = 600
maximum_intensity = 1.2
end_of_attack = maximum_intensity * initial_duration
end_of_decay = end_of_attack +( maximum_intensity - 1 )*\
initial_duration
if frame_number < end_of_attack: # A - attack from 0 to
# maximum_intensity, reaching 1 at initial_duration
hull_curve = frame_number / initial_duration
elif frame_number < end_of_decay:
# D - decay from maximum_intensity to 1
width_of_decay = end_of_decay - end_of_attack
goes_from_0_to_1 =( frame_number - end_of_attack )\
/width_of_decay
goes_from_maximum_intensity_to_0 = maximum_intensity *\
( end_of_decay - frame_number )/ width_of_decay
hull_curve = goes_from_0_to_1 +\
goes_from_maximum_intensity_to_0
elif integral_duration - initial_duration < frame_number:
# R release
hull_curve =( integral_duration - frame_number )\
/ initial_duration
else: # S - sustain at 1
hull_curve = 1
return hull_curve

def accompanying_hull_curve_of\
( frame_number, frequency_multiplier,
attack_duration, attack_duration_ ):
'''
/\
AD
attack-decay curve
attack: rise to maximum_intensity until ...
decay: then fall to 0 until ...
'''
if frame_number - frequency_multiplier < attack_duration_:
if frame_number < attack_duration:
# A - attack
hull_curve_for_accompanying_sound = \
frame_number / attack_duration
else:
# D - decay
hull_curve_for_accompanying_sound = \
1 -( frame_number - attack_duration )/attack_duration_
else:
hull_curve_for_accompanying_sound = 0
return hull_curve_for_accompanying_sound

def record_instrument_value( instrument_value ):
global write_position
frame_value = instrument_value
if reverb:
frame_value += some_reverb()
record_signal_for_reverb( frame_value )
frame_values[ write_position ]= round( 32767/3 * frame_value )
write_position+=1

class instrument0:
halftone_step = 2**( 1/12 )
base_duration = 4
attack_duration = base_duration * 60
release_duration = base_duration * 100
frequency_factor = 5 * halftone_step
base_duration_1 = 5
attack_duration_1 = base_duration_1 * 100
release_duration_1 = base_duration_1 * 240
frequency_factor_1 =( 12 + 5 )* halftone_step
frequency_multiplier = 0
def instrument_of( self, frame_number ):
current_angle = self.frequency_multiplier * frame_number

hull_curve = \
hull_curve_of( frame_number, self.integral_duration )

if sine:
if hull_curve:
frame_value = hull_curve *( sin( current_angle ) )
else:
frame_value = sin( current_angle )
else:
if hull_curve:
frame_value = \
hull_curve *\
( sin( current_angle )+
sin( 2 * current_angle )/3 +
sin( 4 * current_angle )/6 +
sin( 8 * current_angle )/12 )
if intro:
hull_curve_for_accompanying_sound = \
accompanying_hull_curve_of\
( frame_number, self.frequency_multiplier,
self.attack_duration, self.release_duration )
if hull_curve_for_accompanying_sound:
frame_value += \
strong_noise\
( self.intensity_of_first_accompanying_sound *
hull_curve_for_accompanying_sound *
sin( self.frequency_factor * current_angle ))
hull_curve_for_second_accompanying_sound = \
accompanying_hull_curve_of\
( frame_number, self.frequency_multiplier,
self.attack_duration_1, self.release_duration_1 )
if hull_curve_for_second_accompanying_sound:
frame_value += \
strong_noise\
( self.intensity_of_second_accompanying_sound * \
hull_curve_for_second_accompanying_sound * \
sin( self.frequency_factor_1 * current_angle ))
else:
frame_value =\
( sin( current_angle )+
sin( 2 * current_angle )/3 +
sin( 4 * current_angle )/6 +
sin( 8 * current_angle )/12 )
return weak_noise( frame_value )


Click here to read the complete article
1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor