Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save skilfoy/b1663e8448c0c220d0eaf46fdfe98041 to your computer and use it in GitHub Desktop.
Save skilfoy/b1663e8448c0c220d0eaf46fdfe98041 to your computer and use it in GitHub Desktop.
generating-true-random-numbers-from-ambient-noise.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/skilfoy/b1663e8448c0c220d0eaf46fdfe98041/generating-true-random-numbers-from-ambient-noise.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "W_AlPs5QNjjB"
},
"source": [
"# Generating True Random Numbers from Ambient Noise\n",
"\n",
"In this project, I aim to generate true random numbers by monitoring ambient noise. True random numbers are crucial for applications requiring high levels of unpredictability and security, such as cryptography, secure communications, and data encryption.\n",
"\n",
"Most random number generators rely on deterministic algorithms, making them inherently predictable if the initial state or algorithm is known. These are referred to as pseudorandom number generators (PRNGs). While PRNGs are sufficient for many applications, they may not provide the level of randomness required for cryptographic purposes.\n",
"\n",
"To overcome the limitations of PRNGs, I use ambient noise as a source of entropy. Ambient noise, which includes sounds from the environment such as wind, traffic, and wildlife, is inherently unpredictable and provides an excellent source of randomness. By capturing and processing this noise, I can produce a stream of random numbers that are truly random.\n",
"\n",
"The generated random number stream can be applied in various cryptographic operations, such as key generation, encryption algorithms, and secure data transmission. This project demonstrates the feasibility of using ambient noise for high-quality random number generation, contributing to the field of cryptography and enhancing security measures in digital communications."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jglrwxRKNjjC"
},
"source": [
"## Stage 1: Capture Audio Data\n",
"\n",
"In this stage, we will capture ambient audio data using the `sounddevice` library. This data will serve as the basis for generating random numbers. Below, we detail each step involved in capturing the audio data and explain the purpose of each code block."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "NsiUoCsUNjjD"
},
"source": [
"To interact with the audio hardware and capture sound, we need the `sounddevice` library."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "EJbg6mCK3odL"
},
"outputs": [],
"source": [
"%%capture\n",
"# Install the sounddevice library if you haven't already\n",
"!pip install sounddevice"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sJjkyx3DNjjE"
},
"source": [
"Import the libraries necessary to run the initial capture."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "8vUdrmf4NjjE"
},
"outputs": [],
"source": [
"%%capture\n",
"import numpy as np\n",
"import sounddevice as sd"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oFb0EYEvNjjF"
},
"source": [
"Before capturing audio, it’s essential to identify the available audio input devices. This helps in selecting the correct device for capturing ambient noise."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "dSrAs57DNjjG",
"outputId": "f28ab353-85f7-4cb5-eb91-13f2de2a18a5"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Available audio devices:\n",
" 0 iPhone (2) Microphone, Core Audio (1 in, 0 out)\n",
"> 1 MacBook Pro Microphone, Core Audio (1 in, 0 out)\n",
"< 2 MacBook Pro Speakers, Core Audio (0 in, 2 out)\n",
" 3 Microsoft Teams Audio, Core Audio (2 in, 2 out)\n"
]
}
],
"source": [
"# List all available audio devices\n",
"print(\"Available audio devices:\")\n",
"print(sd.query_devices())"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ANk0cwJHNjjG"
},
"source": [
"*I will use my MacBook Pro's built-in microphone: audio device 1.*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "mR6QI1IlNjjH"
},
"outputs": [],
"source": [
"# Utilize appropriate input device\n",
"input_device_id = 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "wFvhVwYHNjjH"
},
"outputs": [],
"source": [
"# Parameters\n",
"CHUNK = 1024 # Number of audio samples per frame\n",
"FORMAT = 'int16' # 16-bit audio format\n",
"CHANNELS = 1 # Mono audio\n",
"SAMPLE_RATE = 44100 # Sampling rate in Hz\n",
"UPDATE_INTERVAL = 30 # Interval for updating the graph in seconds"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KuO_YKUNNjjH"
},
"source": [
"The `capture_audio` function captures audio data from the specified input device for a given duration. We use the `sounddevice` library to record audio and return the captured audio data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "3KgH-Sp9NjjH"
},
"outputs": [],
"source": [
"def capture_audio(device_id, duration=1):\n",
" print(\"Capturing audio...\")\n",
" audio_data = sd.rec(int(duration * SAMPLE_RATE), samplerate=SAMPLE_RATE, channels=CHANNELS, dtype=FORMAT, device=device_id)\n",
" sd.wait() # Wait until recording is finished\n",
" print(\"Audio data captured.\")\n",
" return audio_data"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QY0TM4OoNjjI"
},
"source": [
"Finally, we capture one second of audio using the specified input device and print the first few samples to verify the capture."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "MgkCzXDvNjjI",
"outputId": "32c409f2-ab78-4e46-d887-30b29f3229a7"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Capturing audio...\n",
"Audio data captured.\n",
"First few audio samples:\n",
"[[ 4]\n",
" [ 8]\n",
" [ 12]\n",
" [ 7]\n",
" [ 2]\n",
" [ 5]\n",
" [ 1]\n",
" [ -3]\n",
" [ -8]\n",
" [-19]]\n"
]
}
],
"source": [
"# Capture 1 second of audio and print the first few samples\n",
"audio_data = capture_audio(input_device_id, 1)\n",
"print(\"First few audio samples:\", audio_data[:10], sep='\\n')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Xs0HMDumNjjI"
},
"source": [
"This output shows the first few samples of the captured audio data, indicating that the audio capture was successful. These samples will be used in subsequent stages to generate random numbers. Every time we run this cell, as expected, we get a completely new array of numbers, and the microphone indicator light comes on my Mac screen, confirming that audio capture is active."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MqNqmdQvNjjI"
},
"source": [
"## Stage 2: Extract Least Significant Bits (LSBs)\n",
"\n",
"In this stage, we will extract the least significant bits (LSBs) from the captured audio data. The LSBs are used because they are the most likely to exhibit randomness due to the noise in the audio signal."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gVKMrcxJNjjI"
},
"source": [
"#### Extract LSBs from Audio Data\n",
"\n",
"We define a function `extract_lsb` that takes the audio samples as input and returns a list of LSBs. This function flattens the array of audio samples and extracts the least significant bit from each sample."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5N6cZnSyNjjI"
},
"source": [
"1. **Flatten the Array**: Audio samples are typically captured as a multi-dimensional array, but for our purposes, we need a one-dimensional array. The `flatten` method converts the array into a single dimension.\n",
"2. **Extract LSBs**: The LSB of each sample is obtained using the bitwise AND operation (`& 1`). This operation isolates the least significant bit of each sample."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "sILLDr4BNjjI"
},
"outputs": [],
"source": [
"# Function to extract LSBs from audio data\n",
"def extract_lsb(audio_samples):\n",
" audio_samples = audio_samples.flatten() # Flatten the array\n",
" lsb_list = [sample & 1 for sample in audio_samples] # Get the least significant bit of each sample\n",
" return lsb_list"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ejp5D9_6NjjI"
},
"source": [
"#### Extract and Print LSBs\n",
"\n",
"Next, we use the `extract_lsb` function to extract the LSBs from the captured audio data. We then print the first few bits to verify the extraction process."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bbfoI_2hNjjI",
"outputId": "055184bd-1b30-4295-8f4b-49cd0643e434"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First few LSBs: [0, 0, 0, 1, 0, 1, 1, 1, 0, 1]\n"
]
}
],
"source": [
"# Extract LSBs and print the first few bits\n",
"lsb_list = extract_lsb(audio_data)\n",
"print(\"First few LSBs:\", lsb_list[:10])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0AVIx-ZKNjjJ"
},
"source": [
"This output shows the first few LSBs extracted from the audio data. The presence of both 0s and 1s indicates that there is variability in the least significant bits, which is essential for generating random numbers.\n",
"\n",
"In the next stage, we will use these LSBs to generate random numbers. By leveraging the inherent randomness in the audio signal's noise, we can produce high-quality random numbers suitable for cryptographic purposes."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hXhwLDk5NjjJ"
},
"source": [
"## Stage 3: Generate Random Numbers from Bits\n",
"\n",
"In this stage, we will generate random numbers using the least significant bits (LSBs) extracted from the audio data. The LSBs provide the entropy needed to produce random numbers."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "I-tRK1GhNjjJ"
},
"source": [
"#### Function to Generate a Random Number from Bits\n",
"\n",
"The function `generate_random_number_from_bits` takes a list of bits and a range (`min_val` to `max_val`) and generates a random number within that range. It constructs a binary number from the bits and ensures the number falls within the desired range."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Frr_3huQNjjJ"
},
"source": [
"1. **Range Calculation**: The function calculates the range of possible values and determines the number of bits needed to cover this range.\n",
"2. **Construct Binary Number**: A binary number is constructed from the provided bits.\n",
"3. **Debugging**: Initial binary number and range value are printed for debugging purposes.\n",
"4. **Range Check and Retry**: If the constructed binary number is out of the desired range, the process is repeated up to a maximum number of retries to avoid infinite loops."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "WIKf-M2UNjjJ"
},
"outputs": [],
"source": [
"# Function to generate random numbers from bits with debugging\n",
"def generate_random_number_from_bits(bits, min_val, max_val):\n",
" range_val = max_val - min_val + 1\n",
" num_bits_needed = range_val.bit_length() # Number of bits needed to cover the range\n",
" binary_number = 0\n",
"\n",
" # Extract enough bits to cover the range\n",
" for i in range(num_bits_needed):\n",
" if i < len(bits):\n",
" binary_number = (binary_number << 1) | bits[i]\n",
" else:\n",
" break\n",
"\n",
" # Debugging: Print the binary number and range value\n",
" print(f\"Initial binary number: {binary_number}, range value: {range_val}\")\n",
"\n",
" # If the number is out of range, repeat the process\n",
" retry_count = 0 # Add a counter to avoid infinite loops\n",
" max_retries = 10 # Maximum retries to avoid infinite loops\n",
" while binary_number >= range_val:\n",
" binary_number = 0\n",
" for i in range(num_bits_needed):\n",
" if i < len(bits):\n",
" binary_number = (binary_number << 1) | bits[i]\n",
" else:\n",
" break\n",
" retry_count += 1\n",
" if retry_count >= max_retries:\n",
" print(\"Max retries reached, breaking out of loop\")\n",
" break\n",
"\n",
" print(f\"Final binary number: {binary_number}\")\n",
" return min_val + binary_number"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "k1Q5p5fcNjjJ"
},
"source": [
"#### Function to Generate a List of Random Numbers from Bits\n",
"\n",
"The function `generate_random_numbers` uses `generate_random_number_from_bits` to generate a list of random numbers from the extracted bits."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JYKSwbhmNjjJ"
},
"source": [
"1. **Initialize List**: Initializes an empty list to store the generated random numbers.\n",
"2. **Generate Numbers**: Iterates over the bits in chunks of 10 to generate the specified number of random numbers.\n",
"3. **Store Numbers**: Adds each generated random number to the list.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "wVllkmMxNjjJ"
},
"outputs": [],
"source": [
"# Function to generate a list of random numbers from bits with debugging\n",
"def generate_random_numbers(bits, count=10, min_val=0, max_val=10):\n",
" random_numbers = []\n",
" for i in range(0, len(bits), 10):\n",
" if len(random_numbers) >= count:\n",
" break\n",
" if i + 10 <= len(bits):\n",
" random_number = generate_random_number_from_bits(bits[i:i+10], min_val, max_val)\n",
" random_numbers.append(random_number)\n",
" return random_numbers"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kunWwYM4NjjJ"
},
"source": [
"#### Generate and Print Random Numbers\n",
"\n",
"Finally, we use the `generate_random_numbers` function to generate random numbers from the LSBs and print the results."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "RSF87JOaNjjJ",
"outputId": "e1a21c5b-ed45-4e7b-f1f6-7ba4f4203aae"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Initial binary number: 1, range value: 11\n",
"Final binary number: 1\n",
"Initial binary number: 13, range value: 11\n",
"Max retries reached, breaking out of loop\n",
"Final binary number: 13\n",
"Initial binary number: 9, range value: 11\n",
"Final binary number: 9\n",
"Initial binary number: 6, range value: 11\n",
"Final binary number: 6\n",
"Initial binary number: 7, range value: 11\n",
"Final binary number: 7\n",
"Initial binary number: 7, range value: 11\n",
"Final binary number: 7\n",
"Initial binary number: 11, range value: 11\n",
"Max retries reached, breaking out of loop\n",
"Final binary number: 11\n",
"Initial binary number: 3, range value: 11\n",
"Final binary number: 3\n",
"Initial binary number: 6, range value: 11\n",
"Final binary number: 6\n",
"Initial binary number: 1, range value: 11\n",
"Final binary number: 1\n",
"Generated random numbers: [1, 13, 9, 6, 7, 7, 11, 3, 6, 1]\n"
]
}
],
"source": [
"# Generate random numbers and print them\n",
"random_numbers = generate_random_numbers(lsb_list, count=10)\n",
"print(\"Generated random numbers:\", random_numbers)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "U9RAISrGNjjK"
},
"source": [
"This output shows the generated random numbers and the debug information for each number. The presence of diverse values indicates that the LSBs are providing the necessary entropy to generate random numbers.\n",
"\n",
"In the next stage, we will put everything together to generate a stream of random numbers for cryptographic or other applications requiring high-quality randomness."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ekHibmK7NjjK"
},
"source": [
"## Stage 4: Continuously Capture Audio and Print Non-Zero Random Numbers\n",
"\n",
"In the final stage, we will continuously capture audio, generate random numbers, print them, and plot their distribution. We ensure that zero values are excluded from the final random numbers. We also set a specific duration for capturing audio and generating random numbers.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_TpjWU3bNjjK"
},
"source": [
"#### Import Required Libraries\n",
"\n",
"We start by importing the necessary libraries for capturing audio, generating random numbers, and plotting the distribution."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "lmHMFFzANjjK"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import sounddevice as sd\n",
"import struct\n",
"import threading\n",
"import time\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6tjE1e4nNjjK"
},
"source": [
"#### Set Audio Parameters\n",
"\n",
"Next, we define the parameters for audio capture, such as the number of samples per frame (`CHUNK`), audio format (`FORMAT`), number of audio channels (`CHANNELS`), sampling rate (`SAMPLE_RATE`), and the duration for capturing audio."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "8VqwGRmiNjjK"
},
"outputs": [],
"source": [
"# Parameters\n",
"CHUNK = 1024 # Number of audio samples per frame\n",
"FORMAT = 'int16' # 16-bit audio format\n",
"CHANNELS = 1 # Mono audio\n",
"SAMPLE_RATE = 44100 # Sampling rate in Hz\n",
"DURATION = 10 # Duration to capture audio in seconds"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "O7ey0Jo2NjjK"
},
"source": [
"#### List Available Audio Devices\n",
"\n",
"We list all available audio devices to select the appropriate input device."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "TzVKKGoXNjjP",
"outputId": "4b36eff8-e0d0-4a3c-f6f8-37309ef883c1"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Available audio devices:\n",
" 0 iPhone (2) Microphone, Core Audio (1 in, 0 out)\n",
"> 1 MacBook Pro Microphone, Core Audio (1 in, 0 out)\n",
"< 2 MacBook Pro Speakers, Core Audio (0 in, 2 out)\n",
" 3 Microsoft Teams Audio, Core Audio (2 in, 2 out)\n"
]
}
],
"source": [
"# List all available audio devices\n",
"print(\"Available audio devices:\")\n",
"print(sd.query_devices())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "u3-HUPJfNjjP"
},
"outputs": [],
"source": [
"# Specify the input device ID (replace with your microphone device ID)\n",
"input_device_id = 1 # This corresponds with my laptop's built-in microphone"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kmapBAGYNjjP"
},
"source": [
"#### Define Shared Data Structures and Lock\n",
"\n",
"We define a shared list to store the random numbers and a lock to manage concurrent access to the list."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ohl8iHxyNjjP"
},
"outputs": [],
"source": [
"# Shared list to store random numbers\n",
"random_numbers = []\n",
"lock = threading.Lock()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "yhMHPACLNjjP"
},
"source": [
"#### Extract LSBs from Audio Data\n",
"\n",
"We define a function to extract the least significant bits (LSBs) from the audio data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1Ec4RQ3zNjjP"
},
"outputs": [],
"source": [
"# Function to extract LSBs from audio data\n",
"def extract_lsb(audio_samples):\n",
" audio_samples = audio_samples.flatten() # Flatten the array\n",
" lsb_list = [sample & 1 for sample in audio_samples] # Get the least significant bit of each sample\n",
" return lsb_list"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iRXZoKgYNjjP"
},
"source": [
"#### Generate Random Float Numbers from Bits\n",
"\n",
"We define a function to generate random float numbers between `0.000000001` and `0.999999999` using 30 bits for 9 significant figures."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QHrvsPi9NjjP"
},
"outputs": [],
"source": [
"# Function to generate random float numbers from bits\n",
"def generate_random_float_from_bits(bits, min_val=0.000000001, max_val=0.999999999):\n",
" binary_string = ''.join(str(bit) for bit in bits[:30]) # Using 30 bits to get a 9 significant figure float\n",
" decimal_value = int(binary_string, 2) / (2**30 - 1) # Normalize the binary value to a float between 0 and 1\n",
" return min_val + (max_val - min_val) * decimal_value"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "TEv6il-oNjjP"
},
"source": [
"#### Generate List of Random Float Numbers\n",
"\n",
"We define a function to generate a list of random float numbers from the extracted bits."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "3F42DbcXNjjP"
},
"outputs": [],
"source": [
"# Function to generate a list of random float numbers from bits\n",
"def generate_random_numbers(bits, count=10):\n",
" random_numbers = []\n",
" for i in range(0, len(bits), 30): # Use 30 bits to generate each random number\n",
" if len(random_numbers) >= count:\n",
" break\n",
" if i + 30 <= len(bits):\n",
" random_number = generate_random_float_from_bits(bits[i:i+30])\n",
" random_numbers.append(random_number)\n",
" return random_numbers"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "X-6EYFFdNjjP"
},
"source": [
"#### Audio Callback Function\n",
"\n",
"The `audio_callback` function processes the audio data, extracts the LSBs, generates random numbers, and prints them."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ggqbAKIGNjjP"
},
"outputs": [],
"source": [
"# Callback function to process audio data\n",
"def audio_callback(indata, frames, time, status):\n",
" audio_samples = np.frombuffer(indata, dtype=np.int16)\n",
" lsb_list = extract_lsb(audio_samples)\n",
" generated_numbers = generate_random_numbers(lsb_list, count=10)\n",
"\n",
" with lock:\n",
" random_numbers.extend(generated_numbers)\n",
"### print(\"Random Numbers: \", generated_numbers)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "RfKLmuWdNjjP"
},
"source": [
"#### Start Recording and Generate Random Numbers\n",
"\n",
"We define a function to start recording audio and generating random numbers for the specified duration."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "lENwz1ABNjjP"
},
"outputs": [],
"source": [
"# Function to start recording audio and generating random numbers\n",
"def start_recording():\n",
" print(\"Recording...\")\n",
" with sd.InputStream(callback=audio_callback, channels=CHANNELS, samplerate=SAMPLE_RATE, dtype=FORMAT, blocksize=CHUNK, device=input_device_id):\n",
" time.sleep(DURATION)\n",
" print(\"Recording stopped.\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xaFWiNhSNjjQ"
},
"source": [
"#### Start Recording in a Separate Thread\n",
"\n",
"We start the recording in a separate thread and wait for it to finish."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2Xpko3BiNjjQ",
"outputId": "52fe7fcf-56ac-41c1-e8a1-98d81bbb920c"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Recording...\n",
"Recording stopped.\n"
]
}
],
"source": [
"# Start recording and generating random numbers in a separate thread\n",
"recording_thread = threading.Thread(target=start_recording)\n",
"recording_thread.daemon = True\n",
"recording_thread.start()\n",
"\n",
"# Wait for the recording to finish\n",
"recording_thread.join()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "YII3zM54NjjQ",
"outputId": "3f20517f-21c1-4601-977b-3a89f96fd4bf"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A short list of random numbers from this run:\n",
"[0.8579786932926861, 0.2239853542453817, 0.7059991073455842, 0.14876595316737456, 0.18076885292894443, 0.16698704742093287, 0.4249067572747993, 0.9300166973905293, 0.967333605479209, 0.5483384201717865]\n"
]
}
],
"source": [
"# Output the final list of random numbers\n",
"with lock:\n",
" print(\"A short list of random numbers from this run:\", random_numbers[:10], sep='\\n')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "N2cNqCs7NjjQ",
"outputId": "829a0949-eedd-4399-fc19-18b147912c08"
},
"outputs": [
{
"data": {
"image/png": "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Xbu2atWqpePHj9tfLVq0kCStXr3aYZvNmjVTnTp1HNoCAgJ04cIFxcfH3+ARo7Ai7OCWcf78eYd/gK/UqVMnNW7cWD179lRQUJAef/xxffrpp3kKPrfddlueJiJXr17dYdlms6latWp5nq+SV4cOHVJISEiO8ahdu7Z9/d9VrFgxxzZKlSqlU6dO/eN+qlevriJFHP+pudp+8qJRo0aKj4/X0qVLNWHCBAUEBOjUqVM5xj8xMdEeOLLn4TRr1kySdObMGYe+Xl5eOS6fXXmchw4dUvny5eXj4+PQr2bNmg7L2cd2Zbv01/EfP35cFy5ccGi/cpz9/f3l5eWlsmXL5mj/p7G/0u23366uXbvq3XffVVJSUp7eezW51StJoaGhubZfWXNISIhKlizp0FajRg1Jsv8O7NmzR9u3b7cH2+xXdr9jx445vL9KlSo56nzuuedUo0YNtWrVShUqVNBTTz113XPOYA3ceo5bwpEjR3TmzBlVq1btqn28vb21du1arV69Wt98842WLl2qTz75RC1atNDy5ctVtGjRf9zP388iuMrVvvgwMzPzumpyhavtx1wxmbkglS1bVhEREZKkyMhI1apVSw899JCmTp1qn3eUmZmp+++/XydPntTgwYNVq1YtlSxZUn/88Ye6d++eI8gW1HheTW77d+XYv/rqq5o/f77Gjh2r9u3b51h/rc9abq5WmytrzsrKUv369TVp0qRc118ZrHL7HQwMDNTWrVu1bNkyffvtt/r2228VGxurbt26OUyWh3VxZge3hPnz50v664/itRQpUkQtW7bUpEmTtGPHDr355ptatWqV/VS5q79xec+ePQ7Lxhjt3bvX4dJAqVKlcr3T58qzInmprVKlSjp69GiOy3q///67fb0rVKpUSXv27MkRKly9H0lq06aNmjVrprfeest+xmTbtm3avXu3Jk6cqMGDB6tdu3aKiIi4oe+bqVSpkpKSknT+/HmH9l27duXol1u79Nfxly1bNsdZjfxWtWpVdenSRbNnz8717M71ftZc5ejRoznObu3evVuS7L8DVatW1cmTJ9WyZUtFRETkeOV25iw3Hh4eatu2rWbMmKF9+/bpmWee0bx587R3716XHhNuToQdWN6qVas0cuRIValSRZ07d75qv5MnT+Zoy/5yvuxbXLP/OF3tNuO8mjdvnkPg+Oyzz5SUlKRWrVrZ26pWraoffvhBaWlp9rbFixfnuEU9L7W1bt1amZmZeueddxzaJ0+eLJvN5rD/G9G6dWslJyfrk08+sbdlZGRo2rRp8vHxsV9OcpXBgwfrxIkTmjNnjqT/O8Pw9zMKxpgbuuW4devWysjI0MyZM+1tmZmZmjZtmkO/8uXLq0GDBpo7d67Dz+S3337T8uXL1bp1a6druBFDhw5Venq6xo0bl2Nd1apVdebMGf3666/2tqSkJH3xxRf5UktGRoZmz55tX05LS9Ps2bNVrlw5hYWFSZIee+wx/fHHH/af6d9dunQpR1jKzZV3DRYpUsT+BaNX3r4Oa+IyFizl22+/1e+//66MjAylpKRo1apVio+PV6VKlfT1119f80sER4wYobVr16pNmzaqVKmSjh07phkzZqhChQpq0qSJpL/+GAQEBGjWrFny9fVVyZIl1ahRo1znCVyP0qVLq0mTJurRo4dSUlI0ZcoUVatWzeEbgHv27KnPPvtMDz74oB577DHt27dPH374ocOE4bzW1rZtW91333169dVXdfDgQd15551avny5vvrqK/Xt2zfHtp3Vq1cvzZ49W927d1dCQoIqV66szz77TOvXr9eUKVOuOYfKGa1atVK9evU0adIkxcTEqFatWqpataoGDhyoP/74Q35+fvrvf/+b5/kuf9e2bVs1btxYL7/8sg4ePKg6dero888/zzH/R5LGjx+vVq1aKTw8XNHR0bp06ZKmTZsmf39/DR8+/AaO1HnZZ3dyu3zz+OOPa/DgwXrkkUf0wgsv6OLFi5o5c6Zq1Kihn3/+2eW1hISEaOzYsTp48KBq1KihTz75RFu3btW7776r4sWLS/rrayM+/fRTPfvss1q9erUaN26szMxM/f777/r000+1bNkyNWzY8Jr76dmzp06ePKkWLVqoQoUKOnTokKZNm6YGDRrY54/B4tx2HxjgQtm3nme/PDw8THBwsLn//vvN1KlTHW6DzXbl7bQrV6407dq1MyEhIcbDw8OEhISYJ554wuzevdvhfV999ZWpU6eOKVasmMOtxs2aNTN169bNtb6r3Xr+8ccfmyFDhpjAwEDj7e1t2rRp43A7dLaJEyea2267zXh6eprGjRubzZs359jmtWrL7Zbic+fOmX79+pmQkBBTvHhxU716dTN+/HiTlZXl0E+53M5tzNVvib9SSkqK6dGj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27bNoa1Hjx6qVauWBg8erNDQUBUvXlwrV65Ux44dJUm7du1SYmKiwsPDJUnh4eF68803dezYMQUGBkqS4uPj5efnpzp16hTsAQGAixWmSxWFqVYrKF4mVJ7B1dxdRqHhtrDj6+urevXqObSVLFlSZcqUsbdHR0erf//+Kl26tPz8/PT8888rPDxc99xzjyTpgQceUJ06ddS1a1eNGzdOycnJGjp0qGJiYjhzA6DQKqyXKoCblVsnKP+TyZMnq0iRIurYsaNSU1MVGRmpGTNm2NcXLVpUixcvVu/evRUeHq6SJUsqKipKI0aMcGPVAHBjCuOlikv7N+vMug/dXQaQq5sq7KxZs8Zh2cvLS9OnT9f06dOv+p5KlSppyZIl+VwZABS8wnSpIv3EYXeXAFyV279nBwAAID8RdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKW5NezMnDlTd9xxh/z8/OTn56fw8HB9++239vWXL19WTEyMypQpIx8fH3Xs2FEpKSkO20hMTFSbNm1UokQJBQYGatCgQcrIyCjoQwEAADcpt4adChUqaMyYMUpISNDmzZvVokULtWvXTtu3b5ck9evXT//73/+0aNEifffddzp69Kg6dOhgf39mZqbatGmjtLQ0bdiwQXPnzlVcXJxef/11dx0SAAC4yRRz587btm3rsPzmm29q5syZ+uGHH1ShQgW9//77+uijj9SiRQtJUmxsrGrXrq0ffvhB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efnyZT377LM57sb6/PPPr2t7S5cudViOi4tTYGCgEhIS9J///EdnzpzR+++/r48++kgtWrSQJMXGxqp27dr64YcfdM8992j58uXasWOHVqxYoaCgIDVo0EAjR47U4MGDNXz4cHl4eOTlEAEAgMXk6cxOVFSUAgMD5e/vL39/f3Xp0kUhISH25eyXs86cOSNJKl26tCQpISFB6enpioiIsPepVauWKlasqI0bN0qSNm7cqPr16ztMko6MjNTZs2e1ffv2XPeTmpqqs2fPOrwAAIA15enMTmxsbH7VoaysLPXt21eNGzdWvXr1JEnJycny8PBQQECAQ9+goCAlJyfb+1x5N1j2cnafK40ePVpvvPGGi48AAADcjG5ogrIrxcTE6LffftPChQvzfV9DhgzRmTNn7K/Dhw/n+z4BAIB7OPUNyq7Wp08fLV68WGvXrlWFChXs7cHBwUpLS9Pp06cdzu6kpKQoODjY3uenn35y2F723VrZfa7k6elpn3cEAACsza1ndowx6tOnj7744gutWrVKVapUcVgfFham4sWLa+XKlfa2Xbt2KTExUeHh4ZKk8PBwbdu2TceOHbP3iY+Pl5+fn+rUqVMwBwIAAG5abj2zExMTo48++khfffWVfH197XNs/P395e3tLX9/f0VHR6t///4qXbq0/Pz89Pzzzys8PFz33HOPJOmBBx5QnTp11LVrV40bN07JyckaOnSoYmJiOHsDAADcG3ZmzpwpSWrevLlDe2xsrLp37y5Jmjx5sooUKaKOHTsqNTVVkZGRmjFjhr1v0aJFtXjxYvXu3Vvh4eEqWbKkoqKiNGLEiII6DAAAcBNza9i5nm9g9vLy0vTp0zV9+vSr9qlUqZKWLFniytIAAIBF3DR3YwEAAOQHwg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0wg4AALA0t4adtWvXqm3btgoJCZHNZtOXX37psN4Yo9dff13ly5eXt7e3IiIitGfPHoc+J0+eVOfOneXn56eAgABFR0fr/PnzBXgUAADgZubWsHPhwgXdeeedmj59eq7rx40bp7fffluzZs3Sjz/+qJIlSyoyMlKXL1+29+ncubO2b9+u+Ph4LV68WGvXrlWvXr0K6hAAAMBNrpg7d96qVSu1atUq13XGGE2ZMkVDhw5Vu3btJEnz5s1TUFCQvvzySz3++OPauXOnli5dqk2bNqlhw4aSpGnTpql169aaMGGCQkJCCuxYAADAzemmnbNz4MABJScnKyIiwt7m7++vRo0aaePGjZKkjRs3KiAgwB50JCkiIkJFihTRjz/+WOA1AwCAm49bz+xcS3JysiQpKCjIoT0oKMi+Ljk5WYGBgQ7rixUrptKlS9v75CY1NVWpqan25bNnz7qqbAAAcJO5ac/s5KfRo0fL39/f/goNDXV3SQAAIJ/ctGEnODhYkpSSkuLQnpKSYl8XHBysY8eOOazPyMjQyZMn7X1yM2TIEJ05c8b+Onz4sIurBwAAN4ubNuxUqVJFwcHBWrlypb3t7Nmz+vHHHxUeHi5JCg8P1+nTp5WQkGDvs2rVKmVlZalRo0ZX3banp6f8/PwcXgAAwJrcOmfn/Pnz2rt3r335wIED2rp1q0qXLq2KFSuqb9++GjVqlKpXr64qVarotddeU0hIiNq3by9Jql27th588EE9/fTTmjVrltLT09WnTx89/vjj3IkFAAAkuTnsbN68Wffdd599uX///pKkqKgoxcXF6aWXXtKFCxfUq1cvnT59Wk2aNNHSpUvl5eVlf8+CBQvUp08ftWzZUkWKFFHHjh319ttvF/ixAACAm5Nbw07z5s1ljLnqepvNphEjRmjEiBFX7VO6dGl99NFH+VEeAACwgJt2zg4AAIArEHYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClWSbsTJ8+XZUrV5aXl5caNWqkn376yd0lAQCAm4Alws4nn3yi/v37a9iwYfr555915513KjIyUseOHXN3aQAAwM0sEXYmTZqkp59+Wj169FCdOnU0a9YslShRQh988IG7SwMAAG5W6MNOWlqaEhISFBERYW8rUqSIIiIitHHjRjdWBgAAbgbF3F3AjTp+/LgyMzMVFBTk0B4UFKTff/891/ekpqYqNTXVvnzmzBlJ0tmzZ11a2/nz5//aX/JeZaVddum280v6icOSqDm/FcaapcJZNzUXDGouGIWy5pNHJP31N9HVf2ezt2eMuXZHU8j98ccfRpLZsGGDQ/ugQYPM3Xffnet7hg0bZiTx4sWLFy9evCzwOnz48DWzQqE/s1O2bFkVLVpUKSkpDu0pKSkKDg7O9T1DhgxR//797ctZWVk6efKkypQpI5vN5rLazp49q9DQUB0+fFh+fn4u2y4cMc4Fh7EuGIxzwWCcC0Z+jrMxRufOnVNISMg1+xX6sOPh4aGwsDCtXLlS7du3l/RXeFm5cqX69OmT63s8PT3l6enp0BYQEJBvNfr5+fGLVAAY54LDWBcMxrlgMM4FI7/G2d/f/x/7FPqwI0n9+/dXVFSUGjZsqLvvvltTpkzRhQsX1KNHD3eXBgAA3MwSYadTp076888/9frrrys5OVkNGjTQ0qVLc0xaBgAAtx5LhB1J6tOnz1UvW7mLp6enhg0bluOSGVyLcS44jHXBYJwLBuNcMG6GcbYZ80/3awEAABRehf5LBQEA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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Plot the distribution of the random numbers\n",
"plt.hist(random_numbers, bins=10, edgecolor='black')\n",
"plt.title('Distribution of Random Numbers')\n",
"plt.xlabel('Value Range')\n",
"plt.ylabel('Frequency')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"source": [
"## Final RNG Runs and Observations"
],
"metadata": {
"id": "wJhZoMitTzEp"
}
},
{
"cell_type": "markdown",
"metadata": {
"id": "qPU9MKa4NjjQ"
},
"source": [
"#### Output Final Random Numbers and Plot Distribution\n",
"\n",
"We print the final list of random numbers and plot their distribution.\n",
"\n",
"* **Multiple Runs**: The graphs show the distribution of the random numbers generated during multiple runs of the script. Each run produces a slightly different distribution, demonstrating the randomness and variability of the generated numbers.\n",
"* **Non-Zero Random Numbers**: The final list of random numbers excludes zero values, ensuring that all generated numbers fall within the specified range and have the desired precision.\n",
"* **Histogram Plot**: The histogram plots provide a visual representation of the distribution of the random numbers, divided into 10 buckets. Each bucket represents a tenth of the range of values from 0 to 1, ensuring that the distribution covers the entire range uniformly. The variability in each run confirms that the random numbers generated are not biased and follow an expected random distribution pattern."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pZEwH3QoNjjQ"
},
"source": [
"Next, I'll set the generator to run for 30 seconds, and I'll plot the distribution of the generated numbers."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "NMX2VK6aNjjQ",
"outputId": "9c8bd820-e137-4ed3-b251-6bfe3acf23cb"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Recording...\n",
"Recording stopped.\n",
"A short list of random numbers from this run:\n",
"[0.03563435751279069, 0.5542665062823613, 0.4591205376637248, 0.07208787369637021, 0.9970121867299887, 0.2639089205962705, 0.6546001586342219, 0.6625176857351452, 0.24312660544622505, 0.06222699769058951]\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkQAAAHHCAYAAABeLEexAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABFLklEQVR4nO3dd3wVVf7/8fcN4SYhpBAgCZFQpFdZYc1GQBAioYiguIJSAkaxgApYEEVAQOlIEUFRaYIorrIsIhKKgoAIkSgCAkoJSorUEErq+f3BL/fLJQFJSGVez8djHo+dM+fOfOaQmPfOnJlrM8YYAQAAWJhLURcAAABQ1AhEAADA8ghEAADA8ghEAADA8ghEAADA8ghEAADA8ghEAADA8ghEAADA8ghEAADA8ghEwDWMGjVKNputUI7VunVrtW7d2rH+zTffyGaz6bPPPiuU4/ft21fVqlUrlGPlVXJysh577DEFBgbKZrNp0KBBRV1Srhw+fFg2m03z588v6lJKhNatW6thw4ZFXQYsgkAEy5g/f75sNptjcXd3V1BQkMLDwzVjxgydPXs2X45z7NgxjRo1SjExMfmyv/xUnGu7Hm+++abmz5+vp556SosWLVLv3r2v2rdatWpO/96enp664447tHDhwkKsuPjLGqdnnnkm27bCDuVAUXIt6gKAwjZ69GhVr15daWlpio+P1zfffKNBgwZp6tSpWrFihRo3buzoO3z4cL388su52v+xY8f0+uuvq1q1amrSpMl1f27NmjW5Ok5eXKu2uXPnKjMzs8BruBHr16/Xv/71L40cOfK6+jdp0kTPP/+8JCkuLk7vv/++IiIilJKSoscff7wgSy1x5s6dq2HDhikoKKioSwGKBFeIYDkdOnRQr1691K9fPw0bNkxff/211q5dq8TERN133326cOGCo6+rq6vc3d0LtJ7z589Lkux2u+x2e4Ee61pKly4tNze3Ijv+9UhMTJSvr+9197/lllvUq1cv9erVSy+++KK+++47lS1bVm+99VbBFVkCNWjQQBkZGRo/fnxRl1LoMjMzdfHixaIuA8UAgQiQ1KZNG7322ms6cuSIPvroI0d7TnOIoqKi1KJFC/n6+qps2bKqU6eOXnnlFUmXbjH885//lCT169fPcbsma85I1pyI6Oho3XXXXSpTpozjs1fOIcqSkZGhV155RYGBgfL0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HS3p0hW+evXqqW7dujp+/LhjadOmjSRpw4YNTvts1aqV6tev79Tm6+urc+fOKSoq6gbPGCUVgQi4THJystN/pK/UvXt3NW/eXI899pgCAgLUo0cPffrpp7kKR7fcckuuJk/XqlXLad1ms6lmzZq5nj+TW0eOHFFQUFC28ahXr55j++WqVKmSbR/lypXTqVOn/vY4tWrVkouL83+Ornac3AgJCVFUVJRWr16tyZMny9fXV6dOnco2/rGxsY5QkjUvqFWrVpKkM2fOOPV1d3fPdqvuyvM8cuSIKlWqpLJlyzr1q1OnjtN61rld2S5dOv/jx4/r3LlzTu1XjrOPj4/c3d1VoUKFbO1/N/ZXuvXWW9W7d2+99957iouLy9VnryaneiUpODg4x/Yraw4KCpKnp6dTW+3atSXJ8Ttw4MAB7d692xF+s5asfomJiU6fr169erY6n376adWuXVsdOnRQ5cqV9eijj173HDjcHHjsHvj//vjjD505c0Y1a9a8ah8PDw9t3LhRGzZs0JdffqnVq1frk08+UZs2bbRmzRqVKlXqb49z+dWI/HK1l0dmZGRcV0354WrHMVdMwC5MFSpUUFhYmCQpPDxcdevW1b333qvp06c75kFlZGTonnvu0cmTJzV06FDVrVtXnp6e+vPPP9W3b99sYbewxvNqcjp+fo79q6++qkWLFmnChAnq2rVrtu3X+lnLydVqy8+aMzMz1ahRI02dOjXH7VeGr5x+B/39/RUTE6Ovv/5aX331lb766ivNmzdPffr0cZrgj5sXV4iA/2/RokWSLv3hvBYXFxe1bdtWU6dO1Z49e/TGG29o/fr1jsvy+f1m6wMHDjitG2P022+/Od2GKFeuXI5PMF15dSU3tVWtWlXHjh3Ldgvx119/dWzPD1WrVtWBAweyBY/8Po4kderUSa1atdKbb77puPKya9cu7d+/X1OmTNHQoUPVpUsXhYWF3dD7eKpWraq4uDglJyc7te/bty9bv5zapUvnX6FChWxXRwpajRo11KtXL7377rs5XiW63p+1/HLs2LFsV8n2798vSY7fgRo1aujkyZNq27atwsLCsi05XYHLid1uV+fOnfXOO+/o999/1xNPPKGFCxfqt99+y9dzQvFEIAJ06amTMWPGqHr16urZs+dV+508eTJbW9YLDrMe7836A3a1R6xza+HChU6h5LPP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nPZx+TGu5ObmJm9vb6cFAADcvIptIKpevboCAwO1bt06R1tSUpK2bdum0NBQSVJoaKhOnz6t6OhoR5/169crMzNTISEhjj4bN25UWlqao09UVJTq1KmjcuXKFdLZAACA4qxIA1FycrJiYmIUExMj6dJE6piYGMXGxspms2nQoEEaO3asVqxYoV27dqlPnz4KCgpS165dJUn16tVT+/bt9fjjj+uHH37Q5s2bNXDgQPXo0UNBQUGSpEceeUR2u12RkZHavXu3PvnkE02fPl1DhgwporMGAADFTZE+dr9jxw7dfffdjvWskBIREaH58+frpZde0rlz59S/f3+dPn1aLVq00OrVq+Xu7u74zOLFizVw4EC1bdtWLi4u6tatm2bMmOHY7uPjozVr1mjAgAFq2rSpKlSooBEjRvDIPQAAcCjSQNS6dWsZY6663WazafTo0Ro9evRV+/j5+WnJkiXXPE7jxo21adOmPNcJAABubsV2DhEAAEBhIRABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLIxABAADLy1MgOnjwYH7XAQAAUGTyFIhq1qypu+++Wx999JEuXryY3zUBAAAUqjwFoh9//FGNGzfWkCFDFBgYqCeeeEI//PBDftemjIwMvfbaa6pevbo8PDxUo0YNjRkzRsYYRx9jjEaMGKFKlSrJw8NDYWFhOnDggNN+Tp48qZ49e8rb21u+vr6KjIxUcnJyvtcLAABKpjwFoiZNmmj69Ok6duyYPvzwQ8XFxalFixZq2LChpk6dqr/++itfipswYYJmz56tt99+W3v37tWECRM0ceJEzZw509Fn4sSJmjFjhubMmaNt27bJ09NT4eHhTleuevbsqd27dysqKkorV67Uxo0b1b9//3ypEQAAlHw3NKna1dVVDzzwgJYtW6YJEybot99+0wsvvKDg4GD16dNHcXFxN1Tcli1b1KVLF3Xq1EnVqlXTgw8+qHbt2jmuRhljNG3aNA0fPlxdunRR48aNtXDhQh07dkzLly+XJO3du1erV6/W+++/r5CQELVo0UIzZ87U0qVLdezYsRuqDwAA3BxuKBDt2LFDTz/9tCpVqqSpU6fqhRde0O+//66oqCgdO3ZMXbp0uaHi7rzzTq1bt0779++XJP3000/67rvv1KFDB0nSoUOHFB8fr7CwMMdnfHx8FBISoq1bt0qStm7dKl9fXzVr1szRJywsTC4uLtq2bVuOx01JSVFSUpLTAgAAbl6uefnQ1KlTNW/ePO3bt08dO3bUwoUL1bFjR7m4XMpX1atX1/z581WtWrUbKu7ll19WUlKS6tatq1KlSikjI0NvvPGGevbsKUmKj4+XJAUEBDh9LiAgwLEtPj5e/v7+TttdXV3l5+fn6HOlcePG6fXXX7+h2gEAQMmRp0A0e/ZsPfroo+rbt68qVaqUYx9/f3998MEHN1Tcp59+qsWLF2vJkiVq0KCBYmJiNGjQIAUFBSkiIuKG9n0tw4YN05AhQxzrSUlJCg4OLrDjAQCAopWnQHTlU1w5sdvtNxxaXnzxRb388svq0aOHJKlRo0Y6cuSIxo0bp4iICAUGBkqSEhISnIJZQkKCmjRpIkkKDAxUYmKi037T09N18uRJx+ev5ObmJjc3txuqHQAAlBx5mkM0b948LVu2LFv7smXLtGDBghsuKsv58+cdt+GylCpVSpmZmZIu3ZoLDAzUunXrHNuTkpK0bds2hYaGSpJCQ0N1+vRpRUdHO/qsX79emZmZCgkJybdaAQBAyZWnQDRu3DhVqFAhW7u/v7/efPPNGy4qS+fOnfXGG2/oyy+/1OHDh/XFF19o6tSpuv/++yVJNptNgwYN0tixY7VixQrt2rVLffr0UVBQkLp27SpJqlevntq3b6/HH39cP/zwgzZv3qyBAweqR48eCgoKyrdaAQBAyZWnW2axsbGqXr16tvaqVasqNjb2hovKMnPmTL322mt6+umnlZiYqKCgID3xxBMaMWKEo89LL72kc+fOqX///jp9+rRatGih1atXy93d3dFn8eLFGjhwoNq2bSsXFxd169ZNM2bMyLc6AQBAyZanQOTv76+ff/4521NkP/30k8qXL58fdUmSvLy8NG3aNE2bNu2qfWw2m0aPHq3Ro0dftY+fn5+WLFmSb3UBAICbS55umT388MN69tlntWHDBmVkZCgjI0Pr16/Xc88955gADQAAUFLk6QrRmDFjdPjwYbVt21aurpd2kZmZqT59+uTrHCIAAIDCkKdAZLfb9cknn2jMmDH66aef5OHhoUaNGqlq1ar5XR8AAECBy1MgylK7dm3Vrl07v2oBAAAoEnkKRBkZGZo/f77WrVunxMREx3uBsqxfvz5figMAACgMeQpEzz33nObPn69OnTqpYcOGstls+V0XAABAoclTIFq6dKk+/fRTdezYMb/rAQAAKHR5euzebrerZs2a+V0LAABAkchTIHr++ec1ffp0GWPyux4AAIBCl6dbZt999502bNigr776Sg0aNFDp0qWdtn/++ef5UhwAAEBhyFMg8vX1dXzBKgAAQEmXp0A0b968/K4DAACgyORpDpEkpaena+3atXr33Xd19uxZSdKxY8eUnJycb8UBAAAUhjxdITpy5Ijat2+v2NhYpaSk6J577pGXl5cmTJiglJQUzZkzJ7/rBAAAKDB5ukL03HPPqVmzZjp16pQ8PDwc7ffff7/WrVuXb8UBAAAUhjxdIdq0aZO2bNkiu93u1F6tWjX9+eef+VIYAABAYcnTFaLMzExlZGRka//jjz/k5eV1w0UBAAAUpjwFonbt2mnatGmOdZvNpuTkZI0cOZKv8wAAACVOnm6ZTZkyReHh4apfv74uXryoRx55RAcOHFCFChX08ccf53eNAAAABSpPgahy5cr66aeftHTpUv38889KTk5WZGSkevbs6TTJGgAAoCTIUyCSJFdXV/Xq1Ss/awEAACgSeQpECxcuvOb2Pn365KkYAACAopCnQPTcc885raelpen8+fOy2+0qU6YMgQgAAJQoeXrK7NSpU05LcnKy9u3bpxYtWjCpGgAAlDh5/i6zK9WqVUvjx4/PdvUIAACguMu3QCRdmmh97Nix/NwlAABAgcvTHKIVK1Y4rRtjFBcXp7ffflvNmzfPl8IAAAAKS54CUdeuXZ3WbTabKlasqDZt2mjKlCn5URcAAEChyVMgyszMzO86AAAAiky+ziECAAAoifJ0hWjIkCHX3Xfq1Kl5OQQAAEChyVMg2rlzp3bu3Km0tDTVqVNHkrR//36VKlVKt99+u6OfzWbLnyoBAAAKUJ4CUefOneXl5aUFCxaoXLlyki69rLFfv35q2bKlnn/++XwtEgAAoCDlaQ7RlClTNG7cOEcYkqRy5cpp7NixPGUGAABKnDwFoqSkJP3111/Z2v/66y+dPXv2hosCAAAoTHkKRPfff7/69eunzz//XH/88Yf++OMP/ec//1FkZKQeeOCB/K4RAACgQOVpDtGcOXP0wgsv6JFHHlFaWtqlHbm6KjIyUpMmTcrXAgEAAApangJRmTJl9M4772jSpEn6/fffJUk1atSQp6dnvhYHAABQGG7oxYxxcXGKi4tTrVq15OnpKWNMftUFAABQaPIUiE6cOKG2bduqdu3a6tixo+Li4iRJkZGRPHIPAABKnDwFosGDB6t06dKKjY1VmTJlHO3du3fX6tWr8604AACAwpCnOURr1qzR119/rcqVKzu116pVS0eOHMmXwgAAAApLnq4QnTt3zunKUJaTJ0/Kzc3thou63J9//qlevXqpfPny8vDwUKNGjbRjxw7HdmOMRowYoUqVKsnDw0NhYWE6cOBAtrp69uwpb29v+fr6KjIyUsnJyflaJwAAKLnyFIhatmyphQsXOtZtNpsyMzM1ceJE3X333flW3KlTp9S8eXOVLl1aX331lfbs2aMpU6Y4vSF74sSJmjFjhubMmaNt27bJ09NT4eHhunjxoqNPz549tXv3bkVFRWnlypXauHGj+vfvn291AgCAki1Pt8wmTpyotm3baseOHUpNTdVLL72k3bt36+TJk9q8eXO+FTdhwgQFBwdr3rx5jrbq1as7/rcxRtOmTdPw4cPVpUsXSdLChQsVEBCg5cuXq0ePHtq7d69Wr16t7du3q1mzZpKkmTNnqmPHjpo8ebKCgoLyrV4AAFAy5ekKUcOGDbV//361aNFCXbp00blz5/TAAw9o586dqlGjRr4Vt2LFCjVr1kz//ve/5e/vr3/84x+aO3euY/uhQ4cUHx+vsLAwR5uPj49CQkK0detWSdLWrVvl6+vrCEOSFBYWJhcXF23bti3H46akpCgpKclpAQAAN69cXyFKS0tT+/btNWfOHL366qsFUZPDwYMHNXv2bA0ZMkSvvPKKtm/frmeffVZ2u10RERGKj4+XJAUEBDh9LiAgwLEtPj5e/v7+TttdXV3l5+fn6HOlcePG6fXXXy+AMwIAAMVRrq8QlS5dWj///HNB1JJNZmambr/9dr355pv6xz/+of79++vxxx/XnDlzCvS4w4YN05kzZxzL0aNHC/R4AACgaOXpllmvXr30wQcf5Hct2VSqVEn169d3aqtXr55iY2MlSYGBgZKkhIQEpz4JCQmObYGBgUpMTHTanp6erpMnTzr6XMnNzU3e3t5OCwAAuHnlaVJ1enq6PvzwQ61du1ZNmzbN9h1mU6dOzZfimjdvrn379jm17d+/X1WrVpV0aYJ1YGCg1q1bpyZNmkiSkpKStG3bNj311FOSpNDQUJ0+fVrR0dFq2rSpJGn9+vXKzMxUSEhIvtQJAABKtlwFooMHD6patWr65ZdfdPvtt0u6FFAuZ7PZ8q24wYMH684779Sbb76phx56SD/88IPee+89vffee45jDRo0SGPHjlWtWrVUvXp1vfbaawoKClLXrl0lXbqi1L59e8ettrS0NA0cOFA9evTgCTMAACApl4GoVq1aiouL04YNGyRd+qqOGTNmZJvUnF/++c9/6osvvtCwYcM0evRoVa9eXdOmTVPPnj0dfV566SWdO3dO/fv31+nTp9WiRQutXr1a7u7ujj6LFy/WwIED1bZtW7m4uKhbt26aMWNGgdQMAABKnlwFoiu/zf6rr77SuXPn8rWgK91777269957r7rdZrNp9OjRGj169FX7+Pn5acmSJQVRHgAAuAnkaVJ1lisDEgAAQEmUq0Bks9myzRHKzzlDAAAARSHXt8z69u3r+ALXixcv6sknn8z2lNnnn3+efxUCAAAUsFwFooiICKf1Xr165WsxAAAARSFXgejyL1kFAAC4WdzQpGoAAICbAYEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYHoEIAABYXokKROPHj5fNZtOgQYMcbRcvXtSAAQNUvnx5lS1bVt26dVNCQoLT52JjY9WpUyeVKVNG/v7+evHFF5Wenl7I1QMAgOKqxASi7du3691331Xjxo2d2gcPHqz//e9/WrZs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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"DURATION = 30 # Duration to capture audio in seconds\n",
"random_numbers = [] # Reinitialize the shared list to store random numbers\n",
"\n",
"# Start recording and generating random numbers in a separate thread\n",
"recording_thread = threading.Thread(target=start_recording)\n",
"recording_thread.daemon = True\n",
"recording_thread.start()\n",
"\n",
"# Wait for the recording to finish\n",
"recording_thread.join()\n",
"\n",
"# Output the final list of random numbers\n",
"with lock:\n",
" print(\"A short list of random numbers from this run:\", random_numbers[:10], sep='\\n')\n",
"\n",
"# Plot the distribution of the random numbers\n",
"plt.hist(random_numbers, bins=10, edgecolor='black')\n",
"plt.title('Distribution of Random Numbers')\n",
"plt.xlabel('Value Range')\n",
"plt.ylabel('Frequency')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Xn4GE50_NjjR"
},
"source": [
"We see significantly more random numbers, as well as a decently random and relatively even distribution across the range. Additionally, every time I run these cells, the graphs appear slightly different. These observations indicates a wide variety and indeed random distribution of numbers being generated.\n",
"\n",
"For reference, nothing particularly random or noisy was happening in my vicinity while running these tests - I've been working on this project during late nights and in my spare time. As such, it's mostly quiet with the exception of a fan or two, perhaps the air conditioning kicking on, and, perhaps the noisiest (at least for my computer's built-in microphone!), the clickety-clack of my keyboard. However, with the exception of the following two cells, I mostly just quietly watched as my code exeecuted. So, having this robustness and randomness of the numbers being generated is promising - it means that even through relative silence, we're getting a high quality stream of random numbers."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lH0amJLBNjjR"
},
"source": [
"Finally, I'll set the generator to run for **five minutes**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "hdfG-zbCNjjR",
"outputId": "c7af4177-9205-44ce-e770-53e79ab430db"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Recording...\n",
"Recording stopped.\n",
"A short list of random numbers from this run:\n",
"[0.27827998600380505, 0.4127404350788602, 0.7188956646703377, 0.551464921274171, 0.4295772449866021, 0.31476571104727064, 0.26174420097227646, 0.3856030000664934, 0.8491921481669953, 0.7451310848991537]\n"
]
},
{
"data": {
"image/png": "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jFq0aGGOVahQQT/++KMSExPNseXLl6d7NEFmemvZsqVSUlI0depUh/GPPvpINpvN4fh3o2XLloqJidGiRYvMseTkZE2ZMkVFixY13ybLLm+//bbOnTunWbNmSfrfFY+br3AYhnFXHzVv2bKlkpOTNX36dHMsJSVFU6ZMcagrXbq0ateurblz5zr8mfzyyy9as2aNWrZsmeUe7saQIUOUlJSksLCwdNsqVKigS5cuac+ePebYmTNn9M0339yTXpKTk/XJJ5+Y64mJifrkk09UqlQpBQYGSpKef/55/fHHH+af6c2uXbuWLnRl5NZPeRYoUMB80O2tjy3A/Ym354AMfPfdd/rtt9+UnJys2NhYrV+/XpGRkfL399eyZcvu+DDLESNGaNOmTWrVqpX8/f119uxZffzxxypTpowaNmwo6cYvFU9PT82YMUNubm4qUqSI6tWrl+F9FFYUL15cDRs2VM+ePRUbG6uJEyeqYsWKDk+07tWrl7766is1b95czz//vH7//Xd9/vnnDjdmZ7a3Nm3a6LHHHtN7772nY8eOqVatWlqzZo2+/fZb9evXL92+s6p379765JNP1KNHD0VFRalcuXL66quvtGXLFk2cOPGO95hlRYsWLVSjRg2Fh4erT58+qlKliipUqKA333xTf/zxh9zd3fXf//430/cD3axNmzZq0KCB3nnnHR07dkzVqlXT119/ne7+KEkaN26cWrRooaCgIIWGhuratWuaMmWKPDw8NHz48Ls406xLu9qU0dtSHTp00Ntvv62nnnpKr7/+uq5evarp06froYce0q5du7K9F19fX40dO1bHjh3TQw89pEWLFik6OlozZ85UoUKFJN14XMjixYv18ssva8OGDWrQoIFSUlL022+/afHixVq9erXq1q17x+P06tVL58+f1+OPP64yZcro+PHjmjJlimrXrm3eX4f7XK59bg/Ig9IeOZC22O12w8fHx3jiiSeMSZMmOXz8Oc2tH6Net26d0bZtW8PX19ew2+2Gr6+v0bFjR+PgwYMOr/v222+NatWqGU5OTg4fMW/cuLFRvXr1DPu73SMHvvjiC2Pw4MGGl5eX4erqarRq1crhY/BpJkyYYDzwwAOGs7Oz0aBBA2Pnzp3p9nmn3jL6KPnly5eN/v37G76+vkahQoWMSpUqGePGjTNSU1Md6pTBx/gN4/aPQrhV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5cvLx8dH69atM7fHxcVp+/btCgoKkiQFBQXp4sWLioqKMmvWr1+v1NRU1atXz6zZtGmTkpKSzJrIyEhVrlxZxYoVu6tzAAAA94cshabw8HAFBASofv36On36tObNm6fjx49r1KhRKl++vBo1aqSIiAjt2rXrrppr06aNPvjgA61YsULHjh3TN998o/DwcD311FOSJJvNpn79+mnUqFFatmyZ9u7dq27dusnX11ft2rWTJFWtWlXNmzfXiy++qJ9++klbtmxR37591aFDB/n6+kqSOnXqJLvdrtDQUO3bt0+LFi3SpEmTNGDAgLvqHwAA3D+y9MiB6dOn64UXXlCPHj1UunTpDGu8vLz02Wef3VVzU6ZM0fvvv69XX31VZ8+ela+vr1566SUNHTrUrHnrrbd05coV9e7dWxcvXlTDhg21atUqubi4mDULFixQ37591bRpUxUoUEDPPPOMJk+ebG738PDQmjVr1KdPHwUGBqpkyZIaOnQojxsAAACmLIWmW5+4nRG73a7u3btnZfcmNzc3TZw4URMnTrxtjc1m04gRIzRixIjb1hQvXlwLFy6847Fq1qypzZs3Z7VVAABwn8vS23Nz5szRkiVL0o0vWbIkT3yyDQAAILtlKTSNHj1aJUuWTDfu5eWlDz/88K6bAgAAyGuyFJpOnDih8uXLpxv39/fXiRMn7ropAACAvCZLocnLy0t79uxJN/7zzz+rRIkSd90UAABAXpOl0NSxY0e9/vrr2rBhg1JSUpSSkqL169frjTfeUIcOHbK7RwAAgFyXpU/PjRw5UseOHVPTpk3l5HRjF6mpqerWrRv3NAEAgPtSlkKT3W7XokWLNHLkSP38889ydXVVQECA/P39s7s/AACAPCFLoSnNQw89pIceeii7egEAAMizshSaUlJSFBERoXXr1uns2bPmd8GlWb9+fbY0BwAAkFdkKTS98cYbioiIUKtWrVSjRg3ZbLbs7gsAACBPyVJo+vLLL7V48WK1bNkyu/sBAADIk7L0yAG73a6KFStmdy8AAAB5VpZC08CBAzVp0iQZhpHd/QAAAORJWXp77ocfftCGDRv03XffqXr16ipUqJDD9q+//jpbmgMAAMgrshSaPD099dRTT2V3LwAAAHlWlkLTnDlzsrsPAACAPC1L9zRJUnJystauXatPPvlEly9fliSdPn1a8fHx2dYc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Q2i6Rd++fTN8Oy43OTs7a9iwYeneDkT2Yp5zBvOcM5jnnME855y8MNc2w7DyGTsAAIB/Nh5uCQAAYAGhCQAAwAJCEwAAgAWEJgAAAAsITXnEtGnTVK5cObm4uKhevXr66aef7li/ZMkSValSRS4uLgoICNDKlStzqNP8LTPzPGvWLDVq1EjFihVTsWLFFBwc/Ld/Lrghsz/Pab788kvZbDbzAbO4s8zO88WLF9WnTx+VLl1azs7Oeuihh/h/hwWZneeJEyeqcuXKcnV1lZ+fn/r376/r1/PH97vllk2bNqlNmzby9fWVzWbT0qVL//Y1GzduVJ06deTs7KyKFSsqIiLinvfJd8/lAV9++aVht9uN2bNnG/v27TNefPFFw9PT04iNjc2wfsuWLUbBggWNsLAw49dffzWGDBliFCpUyNi7d28Od56/ZHaeO3XqZEybNs3YvXu3sX//fqNHjx6Gh4eHcerUqRzuPH/J7DynOXr0qPHAAw8YjRo1Mtq2bZszzeZjmZ3nhIQEo27dukbLli2NH374wTh69KixceNGIzo6Ooc7z18yO88LFiwwnJ2djQULFhhHjx41Vq9ebZQuXdro379/Dneev6xcudJ47733jK+//tqQZHzzzTd3rD9y5IhRuHBhY8CAAcavv/5qTJkyxShYsKCxatWqe9onoSkPeOSRR4w+ffqY6ykpKYavr68xevToDOuff/55o1WrVg5j9erVM1566aV72md+l9l5vlVycrLh5uZmzJ079161eF/IyjwnJycb9evXNz799FOje/fuhCYLMjvP06dPNx588EEjMTExp1q8L2R2nvv06WM8/vjjDmMDBgwwGjRocE/7vJ9YCU1vvfWWUb16dYex9u3bGyEhIfewM8Pg7blclpiYqKioKAUHB5tjBQoUUHBwsLZt25bha7Zt2+ZQL0khISG3rUfW5vlWV69eVVJSkooXL36v2sz3sjrPI0aMkJeXl0JDQ3OizXwvK/O8bNkyBQUFqU+fPvL29laNGjX04YcfKiUlJafazneyMs/169dXVFSU+RbekSNHtHLlSrVs2TJHev6nyK3fgzwRPJf99ddfSklJSfdVLd7e3vrtt98yfE1MTEyG9TExMfesz/wuK/N8q7ffflu+vr7p/qLif7Iyzz/88IM+++wzRUdH50CH94eszPORI0e0fv16de7cWStXrtThw4f16quvKikpScOGDcuJtvOdrMxzp06d9Ndff6lhw4YyDEPJycl6+eWX9e677+ZEy/8Yt/s9GBcXp2vXrsnV1fWeHJcrTYAFY8aM0ZdffqlvvvlGLi4uud3OfePy5cvq2rWrZs2apZIlS+Z2O/e11NRUeXl5aebMmQoMDFT79u313nvvacaMGbnd2n1l48aN+vDDD/Xxxx9r165d+vrrr7VixQqNHDkyt1tDNuBKUy4rWbKkChYsqNjYWIfx2NhY+fj4ZPgaHx+fTNUja/OcZvz48RozZozWrl2rmjVr3ss2873MzvPvv/+uY8eOqU2bNuZYamqqJMnJyUkHDhxQhQoV7m3T+VBWfp5Lly6tQoUKqWDBguZY1apVFRMTo8TERNnt9nvac36UlXl+//331bVrV/Xq1UuSFBAQoCtXrqh379567733VKAA1yqyw+1+D7q7u9+zq0wSV5pynd1uV2BgoNatW2eOpaamat26dQoKCsrwNUFBQQ71khQZGXnbemRtniUpLCxMI0eO1KpVq1S3bt2caDVfy+w8V6lSRXv37lV0dLS5PPnkk3rssccUHR0tPz+/nGw/38jKz3ODBg10+PBhM5RK0sGDB1W6dGkC021kZZ6vXr2aLhilBVWDr3rNNrn2e/Ce3mYOS7788kvD2dnZiIiIMH799Vejd+/ehqenpxETE2MYhmF07drVeOedd8z6LVu2GE5OTsb48eON/fv3G8OGDeORAxZkdp7HjBlj2O1246uvvjLOnDljLpcvX86tU8gXMjvPt+LTc9Zkdp5PnDhhuLm5GX379jUOHDhgLF++3PDy8jJGjRqVW6eQL2R2nocNG2a4ubkZX3zxhXHkyBFjzZo1RoUKFYznn38+t04hX7h8+bKxe/duY/fu3YYkIzw83Ni9e7dx/PhxwzAM45133jG6du1q1qc9cmDQoEHG/v37jWnTpvHIgX+SKVOmGGXLljXsdrvxyCOPGD/++KO5rXHjxkb37t0d6hcvXmw89NBDht1uN6pXr26sWLEihzvOnzIzz/7+/oakdMuwYcNyvvF8JrM/zzcjNFmX2XneunWrUa9ePcPZ2dl48MEHjQ8++MBITk7O4a7zn8zMc1JSkjF8+HCjQoUKhouLi+Hn52e8+uqrxoULF3K+8Xxkw4YNGf7/Nm1uu3fvbjRu3Djda2rXrm3Y7XbjwQcfNObMmXPP+7QZBtcLAQAA/g73NAEAAFhAaAIAALCA0AQAAGABoQkAAMACQhMAAIAFhCYAAAALCE0AAAAWEJoA5HtNmjRRv379crsNAPc5QhOAXNOmTRs1b948w22bN2+WzWbTnj17crirjB07dkw2m81cihcvrsaNG2vz5s253RqAHEJoApBrQkNDFRkZqVOnTqXbNmfOHNWtW1c1a9bMhc5ub+3atTpz5ow2bdokX19ftW7dOt23rQO4PxGaAOSa1q1bq1SpUoqIiHAYj4+P15IlSxQaGqpz586pY8eOeuCBB1S4cGEFBAToiy++uON+bTabli5d6jDm6enpcJyTJ0/q+eefl6enp4oXL662bdvq2LFjf9tziRIl5OPjoxo1aujdd99VXFyctm/fbm6fP3++6tatKzc3N/n4+KhTp046e/asuX3jxo2y2Wxat26d6tatq8KFC6t+/fo6cOCAw3FGjRolLy8vubm5qVevXnrnnXdUu3Zth5pPP/1UVatWlYuLi6pUqaKPP/74b/sHkHWEJgC5xsnJSd26dVNERIRu/hrMJUuWKCUlRR07dtT169cVGBioFStW6JdfflHv3r3VtWtX/fTTT1k+blJSkkJCQuTm5qbNmzdry5YtKlq0qJo3b67ExERL+7h27ZrmzZsnSbLb7Q77HjlypH7++WctXbpUx44dU48ePdK9/r333tOECRO0c+dOOTk56YUXXjC3LViwQB988IHGjh2rqKgolS1bVtOnT3d4/YIFCzR06FB98MEH2r9/vz788EO9//77mjt3bhZmBIAl9/wrgQHgDvbv329IMjZs2GCONWrUyOjSpcttX9OqVStj4MCB5nrjxo2NN954w1yXZHzzzTcOr/Hw8DC/BX3+/PlG5cqVjdTUVHN7QkKC4erqaqxevTrDYx49etSQZLi6uhpFihQxbDabIckIDAw0EhMTb9vrjh07DEnG5cuXDcP437e5r1271qxZsWKFIcm4du2aYRiGUa9ePaNPnz4O+2nQoIFRq1Ytc71ChQrGwoULHWpGjhxpBAUF3bYXAHeHK00AclWVKlVUv359zZ49W5J0+PBhbd68WaGhoZKklJQUjRw5UgEBASpevLiKFi2q1atX68SJE1k+5s8//6zDhw/Lzc1NRYsWVdGiRVW8eHFdv35dv//++x1fu2jRIu3evVv//e9/VbFiRUVERKhQoULm9qioKLVp00Zly5aVm5ubGjduLEnp+r35Xq3SpUtLkvk23oEDB/TII4841N+8fuXKFf3+++8KDQ01+y9atKhGjRr1t/0DyDqn3G4AAEJDQ/Xaa69p2rRpmjNnjipUqGCGjXHjxmnSpEmaOHGiAgICVKRIEfXr1++Ob6PZbDaHt/ukG2+bpYmPj1dgYKAWLFiQ7rWlSpW6Y69+fn6qVKmSKlWqpOTkZD311FP65Zdf5OzsrCtXrigkJEQhISFasGCBSpUqpRMnTigkJCRdvzcHLZvNJklKTU2947Fv7l+SZs2apXr16jlsK1iwoKV9AMg8rjQByHXPP/+8ChQooIULF2revHl64YUXzCCxZcsWtW3bVl26dFGtWrX04IMP6uDBg3fcX6lSpXTmzBlz/dChQ7p69aq5XqdOHR06dEheXl6qWLGiw+Lh4WG572effVZOTk7mDdi//fabzp07pzFjxqhRo0aqUqWKw03gVlWuXFk7duxwGLt53dvbW76+vjpy5Ei6/suXL5/p4wGwhtAEINcVLVpU7du31+DBg3XmzBmHG6crVaqkyMhIbd26Vfv379dLL730tx/xf/zxxzV16lTt3r1bO3fu1Msvv+xwZadz584qWbKk2rZtq82bN+vo0aPauHGjXn/99Qwff3A7NptNr7/+usaMGaOrV6+qbNmystvtmjJlio4cOaJly5Zp5MiRmZ6P1157TZ999pnmzp2rQ4cOadSoUdqzZ48ZJCXpP//5j0aPHq3Jkyfr4MGD2rt3r+bMmaPw8PBMHw+ANYQmAHlCaGioLly4oJCQEPn6+prjQ4YMUZ06dRQSEqImTZrIx8dH7dq1u+O+JkyYID8/PzVq1EidOnXSm2++qcKFC5vbCxcurE2bNqls2bJ6+umnVbVqVYWGhur69etyd3fPVN/du3dXUlKSpk6daj4+YcmSJapWrZrGjBmj8ePHZ2p/0o1QN3jwYL355puqU6eOjh49qh49esjFxcWs6dWrlz799FPNmTNHAQEBaty4sSIiIrjSBNxDNuPWN/4BAHnOE088IR8fH82fPz+3WwH+sbgRHADymKtXr2rGjBkKCQlRwYIF9cUXX2jt2rWKjIzM7daAfzSuNAFAHnPt2jW1adNGu3fv1vXr11W5cmUNGTJETz/9dG63BvyjEZoAAAAs4EZwAAAACwhNAAAAFhCaAAAALCA0AQAAWEBoAgAAsIDQBAAAYAGhCQAAwAJCEwAAgAWEJgAAAAv+H/RF2GeARKhPAAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"DURATION = 300 # Duration to capture audio in seconds\n",
"random_numbers = [] # Reinitialize the shared list to store random numbers\n",
"\n",
"# Start recording and generating random numbers in a separate thread\n",
"recording_thread = threading.Thread(target=start_recording)\n",
"recording_thread.daemon = True\n",
"recording_thread.start()\n",
"\n",
"# Wait for the recording to finish\n",
"recording_thread.join()\n",
"\n",
"# Output the final list of random numbers\n",
"with lock:\n",
" print(\"A short list of random numbers from this run:\", random_numbers[:10], sep='\\n')\n",
"\n",
"# Plot the distribution of the random numbers\n",
"plt.hist(random_numbers, bins=10, edgecolor='black')\n",
"plt.title('Distribution of Random Numbers')\n",
"plt.xlabel('Value Range')\n",
"plt.ylabel('Frequency')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "i_FQaC1UNjjR"
},
"source": [
"We see considerably more numbers generated from the audio stream. This is as expected, since the recording duration is so much greater."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "U6Z9T5U2NjjR"
},
"source": [
"Just for fun, I'll let the generator sample audio for **20 minutes**!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QCDIYInlNjjR",
"outputId": "cda699ec-b398-474f-cdb3-5b16b8ca9636"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Recording...\n",
"Recording stopped.\n",
"A short list of random numbers from this run:\n",
"[0.13059564765904608, 0.9264948330918366, 0.0030680085255031806, 0.9767321254619935, 0.3984640358169665, 0.0410053357730516, 0.7469369547596609, 0.15194110469835986, 0.16614304658313786, 0.3754406400424707]\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAk0AAAHHCAYAAACiOWx7AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABIVUlEQVR4nO3deVRV9f7/8ReDB1AEnADJMeeZK341Mq9DJCmZpt2sHNCwwaBSGi2vmlqaJmqKUZZiZjl0q9tNU3EqS7slSZnzGJqA5oSiMu7fH/3Y1yNIG0IO2POx1lmr/dnvs/f7fIR4rX0+Zx8nwzAMAQAAoEjOjm4AAACgIiA0AQAAWEBoAgAAsIDQBAAAYAGhCQAAwAJCEwAAgAWEJgAAAAsITQAAABYQmgAAACwgNAF/0oQJE+Tk5FQm5+rWrZu6detmbm/atElOTk766KOPyuT8w4YNU4MGDcrkXCV14cIFjRgxQv7+/nJyctKoUaMc3VKxHDlyRE5OToqPj3d0KxVCt27d1Lp1a0e3gb8IQhNwhfj4eDk5OZkPd3d3BQQEKDQ0VG+88YbOnz9fKuc5fvy4JkyYoKSkpFI5Xmkqz71Z8eqrryo+Pl4jR47U4sWLNWTIkGvWNmjQwO7fu0qVKurYsaPee++9Muy4/MufpyeeeKLAvrIO7oAjuTq6AaA8mjhxoho2bKjs7GylpqZq06ZNGjVqlGJiYvTZZ5+pbdu2Zu3YsWP1wgsvFOv4x48f18svv6wGDRooMDDQ8vPWrl1brPOURFG9zZ8/X3l5ede9hz9jw4YNuuWWWzR+/HhL9YGBgXr66aclSSkpKXrnnXcUHh6uzMxMPfzww9ez1Qpn/vz5GjNmjAICAhzdCuAQXGkCCtGrVy8NHjxYw4cP15gxY7RmzRqtW7dOJ06c0N13361Lly6Zta6urnJ3d7+u/Vy8eFGSZLPZZLPZruu5ilKpUiW5ubk57PxWnDhxQj4+Ppbrb7rpJg0ePFiDBw/Ws88+q6+//lqenp6aOXPm9WuyAmrVqpVyc3M1depUR7dS5vLy8nT58mVHt4FygNAEWNSjRw/985//1C+//KL333/fHC9sTVNCQoJuu+02+fj4yNPTU82aNdOLL74o6fe3M/7v//5PkjR8+HDzraH8NSz5azQSExP197//XZUrVzafe/Wapny5ubl68cUX5e/vrypVqujuu+/W0aNH7WoaNGigYcOGFXjulcf8o94KW9OUkZGhp59+WnXr1pWbm5uaNWum119/XYZh2NU5OTkpKipKn376qVq3bi03Nze1atVKq1evLnzCr3LixAlFRETIz89P7u7uateunRYtWmTuz3+b6PDhw1q5cqXZ+5EjRywdP1+tWrXUvHlzHTx40G588+bN+sc//qF69erJzc1NdevW1ejRo+0CtPT7HHl6eurXX39Vv3795OnpqVq1aumZZ55Rbm6uXe3Zs2c1bNgweXt7y8fHR+Hh4Tp79myhfW3YsEFdunRRlSpV5OPjo759+2r37t12Nfk/i/v27dPgwYPl7e2tWrVq6Z///KcMw9DRo0fVt29feXl5yd/fXzNmzLA8Lw0aNNDQoUM1f/58HT9+vMjaa619K+x3Jf/nYsWKFWrZsqU8PDwUHBysHTt2SJLeeustNW7cWO7u7urWrds1/z0TExN16623ysPDQw0bNlRcXFyBmszMTI0fP16NGzc2/w2fe+45ZWZmFtrTkiVL1KpVK7m5uZk/p0uXLlVQUJCqVq0qLy8vtWnTRrNnzy5yPnDjIDQBxZC/Pqaot8l27typu+66S5mZmZo4caJmzJihu+++W998840kqUWLFpo4caIk6ZFHHtHixYu1ePFi/f3vfzePcerUKfXq1UuBgYGaNWuWunfvXmRfr7zyilauXKnnn39eTz75pBISEhQSElLgD/ofsdLblQzD0N13362ZM2fqzjvvVExMjJo1a6Znn31W0dHRBeq//vprPf7447r//vs1bdo0Xb58WQMGDNCpU6eK7OvSpUvq1q2bFi9erEGDBmn69Ony9vbWsGHDzD9YLVq00OLFi1WzZk0FBgaavdeqVatYc5CTk6Njx46pWrVqduMrVqzQxYsXNXLkSM2ZM0ehoaGaM2eOhg4dWuAYubm5Cg0NVY0aNfT666+ra9eumjFjht5++227uevbt68WL16swYMHa/LkyTp27JjCw8MLHG/dunUKDQ3ViRMnNGHCBEVHR2vLli3q3LlzoSFi4MCBysvL09SpU9WpUydNnjxZs2bN0h133KGbbrpJr732mho3bqxnnnlGX331leW5eemll5STk1PqV5s2b96sp59+WuHh4ZowYYJ2796tu+66S7GxsXrjjTf0+OOP69lnn9XWrVv10EMPFXj+mTNn1Lt3bwUFBWnatGmqU6eORo4cqQULFpg1eXl5uvvuu/X666+rT58+mjNnjvr166eZM2dq4MCBBY65YcMGjR49WgMHDtTs2bPVoEEDJSQk6IEHHlC1atX02muvaerUqerWrZv5u42/AAOAaeHChYYk4/vvv79mjbe3t/G3v/3N3B4/frxx5a/SzJkzDUnGyZMnr3mM77//3pBkLFy4sMC+rl27GpKMuLi4Qvd17drV3N64caMhybjpppuM9PR0c3z58uWGJGP27NnmWP369Y3w8PA/PGZRvYWHhxv169c3tz/99FNDkjF58mS7unvvvddwcnIyDhw4YI5JMmw2m93Yjz/+aEgy5syZU+BcV5o1a5YhyXj//ffNsaysLCM4ONjw9PS0e+3169c3wsLCijzelbU9e/Y0Tp48aZw8edLYsWOHMWTIEEOSERkZaVd78eLFAs+fMmWK4eTkZPzyyy/mWHh4uCHJmDhxol3t3/72NyMoKMjczp+7adOmmWM5OTlGly5dCsx/YGCg4evra5w6dcoc+/HHHw1nZ2dj6NCh5lj+z+Ijjzxid8w6deoYTk5OxtSpU83xM2fOGB4eHoX+TBQ2T/lzOnz4cMPd3d04fvy4YRj/+xlcsWKF3Rxc+XNydX9XkmS4ubkZhw8fNsfeeustQ5Lh7+9v9287ZswYQ5Jdbf7vy4wZM8yxzMxMc86ysrIMwzCMxYsXG87OzsbmzZvtzh8XF2dIMr755hu7npydnY2dO3fa1T711FOGl5eXkZOTU9R04QbGlSagmDw9PYv8FF3+epp///vfJV407ebmpuHDh1uuHzp0qKpWrWpu33vvvapdu7ZWrVpVovNbtWrVKrm4uOjJJ5+0G3/66adlGIa++OILu/GQkBA1atTI3G7btq28vLx06NChPzyPv7+/HnjgAXOsUqVKevLJJ3XhwgV9+eWXJX4Na9euVa1atVSrVi21adNGixcv1vDhwzV9+nS7Og8PD/O/MzIy9Ntvv+nWW2+VYRjavn17geM+9thjdttdunSxe52rVq2Sq6urRo4caY65uLgU+IRaSkqKkpKSNGzYMFWvXt0cb9u2re64445C/41HjBhhd8wOHTrIMAxFRESY4z4+PmrWrNkfzv3Vxo4dW+pXm26//Xa7t/M6deokSRowYIDdz3X++NU9u7q66tFHHzW3bTabHn30UZ04cUKJiYmSfr9S2KJFCzVv3ly//fab+ejRo4ckaePGjXbH7Nq1q1q2bGk35uPjo4yMDCUkJPzJV4yKitAEFNOFCxfs/kd+tYEDB6pz584aMWKE/Pz8dP/992v58uXFClA33XRTsRZ8N2nSxG7byclJjRs3LvZ6nuL65ZdfFBAQUGA+WrRoYe6/Ur169Qoco1q1ajpz5swfnqdJkyZydrb/X9a1zlMcnTp1UkJCglavXq3XX39dPj4+OnPmTIH5T05ONoNL/jqlrl27SpLOnTtnV+vu7l7gbcGrX+cvv/yi2rVry9PT066uWbNmdtv5r+3qcen31//bb78pIyPDbvzqefb29pa7u7tq1qxZYPyP5v5qN998s4YMGaK3335bKSkpxXrutRTWryTVrVu30PGrew4ICFCVKlXsxpo2bSpJ5u/A/v37tXPnTjMg5z/y606cOGH3/IYNGxbo8/HHH1fTpk3Vq1cv1alTRw899JDlNXm4MXDLAaAYjh07pnPnzqlx48bXrPHw8NBXX32ljRs3auXKlVq9erWWLVumHj16aO3atXJxcfnD81x5VaO0XOsGnLm5uZZ6Kg3XOo9x1aLxslSzZk2FhIRIkkJDQ9W8eXPdddddmj17trkuKzc3V3fccYdOnz6t559/Xs2bN1eVKlX066+/atiwYQUCcVnN57UUdv7SnPuXXnpJixcv1muvvaZ+/foV2F/Uz1phrtVbafacl5enNm3aKCYmptD9Vwe0wn4HfX19lZSUpDVr1uiLL77QF198oYULF2ro0KF2H0rAjYsrTUAxLF68WNLvf1yL4uzsrNtvv10xMTHatWuXXnnlFW3YsMF8C6C07yC+f/9+u23DMHTgwAG7tzyqVatW6Cezrr5KU5ze6tevr+PHjxd4u3LPnj3m/tJQv3597d+/v0A4Ke3zSFJYWJi6du2qV1991byCs2PHDu3bt08zZszQ888/r759+yokJORP3a+ofv36SklJ0YULF+zG9+7dW6CusHHp99dfs2bNAldZrrdGjRpp8ODBeuuttwq92mT1Z620HD9+vMDVtn379kmS+TvQqFEjnT59WrfffrtCQkIKPAq7klcYm82mPn36aN68eTp48KAeffRRvffeezpw4ECpviaUT4QmwKINGzZo0qRJatiwoQYNGnTNutOnTxcYy79JZP5Hm/P/yF3r4+XF9d5779kF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0FCdOHHi+r94AABQITg8NF24cEGDBg3S/PnzVa1aNXP83LlzevfddxUTE6MePXooKChICxcu1JYtW/Ttt99KktauXatdu3bp/fffV2BgoHr16qVJkyYpNjZWWVlZkqS4uDg1bNhQM2bMUIsWLRQVFaV7771XM2fONM8VExOjhx9+WMOHD1fLli0VFxenypUra8GCBWU7GQAAoNxyeGiKjIxUWFiYQkJC7MYTExOVnZ1tN968eXPVq1dPW7dulSRt3bpVbdq0kZ+fn1kTGhqq9PR07dy506y5+tihoaHmMbKyspSYmGhX4+zsrJCQELMGAADA1ZEnX7p0qX744Qd9//33BfalpqbKZrPJx8fHbtzPz0+pqalmzZWBKX9//r6iatLT03Xp0iWdOXNGubm5hdbs2bPnmr1nZmYqMzPT3E5PT/+DVwsAACoyh11pOnr0qJ566iktWbJE7u7ujmqjxKZMmSJvb2/zUbduXUe3BAAAriOHhabExESdOHFC7du3l6urq1xdXfXll1/qjTfekKurq/z8/JSVlaWzZ8/aPS8tLU3+/v6SJH9//wKfpsvf/qMaLy8veXh4qGbNmnJxcSm0Jv8YhRkzZozOnTtnPo4ePVqieQAAABWDw0LT7bffrh07digpKcl8dOjQQYMGDTL/u1KlSlq/fr35nL179yo5OVnBwcGSpODgYO3YscPuU24JCQny8vJSy5YtzZorj5Ffk38Mm82moKAgu5q8vDytX7/erCmMm5ubvLy87B4AAODG5bA1TVWrVlXr1q3txqpUqaIaNWqY4xEREYqOjlb16tXl5eWlJ554QsHBwbrlllskST179lTLli01ZMgQTZs2TampqRo7dqwiIyPl5uYmSXrsscc0d+5cPffcc3rooYe0YcMGLV++XCtXrjTPGx0drfDwcHXo0EEdO3bUrFmzlJGRoeHDh5fRbAAAgPLOoQvB/8jMmTPl7OysAQMGKDMzU6GhoZo3b56538XFRZ9//rlGjhyp4OBgValSReHh4Zo4caJZ07BhQ61cuVKjR4/W7NmzVadOHb3zzjsKDQ01awYOHKiTJ09q3LhxSk1NVWBgoFavXl1gcTgAAPjrKlehadOmTXbb7u7uio2NVWxs7DWfU79+fa1atarI43br1k3bt28vsiYqKkpRUVGWewUAAH8tDr9PEwAAQEVAaAIAALCA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xtixY41KlSoZO3bsKOPOK5bizvODDz5oxMbGGtu3bzd2795tDBs2zPD29jaOHTtWxp1XLMWd53yHDx82brrpJqNLly5G3759y6bZCqy485yZmWl06NDB6N27t/H1118bhw8fNjZt2mQkJSWVcecVS3HnecmSJYabm5uxZMkS4/Dhw8aaNWuM2rVrG6NHjy7jziuWVatWGS+99JLx8ccfG5KMTz75pMj6Q4cOGZUrVzaio6ONXbt2GXPmzDFcXFyM1atXX9c+CU3lQMeOHY3IyEhzOzc31wgICDCmTJlSaP19991nhIWF2Y116tTJePTRR69rnxVdcef5ajk5OUbVqlWNRYsWXa8WbwglmeecnBzj1ltvNd555x0jPDyc0GRBcef5zTffNG6++WYjKyurrFq8IRR3niMjI40ePXrYjUVHRxudO3e+rn3eSKyEpueee85o1aqV3djAgQON0NDQ69iZYfD2nINlZWUpMTFRISEh5pizs7NCQkK0devWQp+zdetWu3pJCg0NvWY9SjbPV7t48aKys7NVvXr169VmhVfSeZ44caJ8fX0VERFRFm1WeCWZ588++0zBwcGKjIyUn5+fWrdurVdffVW5ubll1XaFU5J5vvXWW5WYmGi+hXfo0CGtWrVKvXv3LpOe/yoc9XeQO4I72G+//abc3NwCX9Xi5+enPXv2FPqc1NTUQutTU1OvW58VXUnm+WrPP/+8AgICCvyi4n9KMs9ff/213n33XSUlJZVBhzeGkszzoUOHtGHDBg0aNEirVq3SgQMH9Pjjjys7O1vjx48vi7YrnJLM84MPPqjffvtNt912mwzDUE5Ojh577DG9+OKLZdHyX8a1/g6mp6fr0qVL8vDwuC7n5UoTYMHUqVO1dOlSffLJJ3J3d3d0OzeM8+fPa8iQIZo/f75q1qzp6HZuaHl5efL19dXbb7+toKAgDRw4UC+99JLi4uIc3doNZdOmTXr11Vc1b948/fDDD/r444+1cuVKTZo0ydGtoRRwpcnBatasKRcXF6WlpdmNp6Wlyd/fv9Dn+Pv7F6seJZvnfK+//rqmTp2qdevWqW3bttezzQqvuPN88OBBHTlyRH369DHH8vLyJEmurq7au3evGjVqdH2broBK8vNcu3ZtVapUSS4uLuZYixYtlJqaqqysLNlstuvac0VUknn+5z//qSFDhmjEiBGS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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"DURATION = 1200 # Duration to capture audio in seconds\n",
"random_numbers = [] # Reinitialize the shared list to store random numbers\n",
"\n",
"# Start recording and generating random numbers in a separate thread\n",
"recording_thread = threading.Thread(target=start_recording)\n",
"recording_thread.daemon = True\n",
"recording_thread.start()\n",
"\n",
"# Wait for the recording to finish\n",
"recording_thread.join()\n",
"\n",
"# Output the final list of random numbers\n",
"with lock:\n",
" print(\"A short list of random numbers from this run:\", random_numbers[:10], sep='\\n')\n",
"\n",
"# Plot the distribution of the random numbers\n",
"plt.hist(random_numbers, bins=10, edgecolor='black')\n",
"plt.title('Distribution of Random Numbers')\n",
"plt.xlabel('Value Range')\n",
"plt.ylabel('Frequency')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "QcN1MLR5NjjR"
},
"source": [
"## Conclusion\n",
"\n",
"This project demonstrates the process of generating true random numbers from ambient noise. By capturing audio from the environment, extracting the least significant bits (LSBs) from the audio samples, and processing these bits to produce random numbers, we ensure high-quality randomness suitable for cryptographic and other security-sensitive applications.\n",
"\n",
"Here is a summary of the key steps and their significance:\n",
"\n",
"1. **Audio Capture**: Using the `sounddevice` library, we capture ambient noise, which serves as the entropy source for generating random numbers.\n",
"2. **LSB Extraction**: The least significant bits from the audio samples are extracted, providing the necessary randomness due to their susceptibility to noise.\n",
"3. **Random Number Generation**: These LSBs are processed to generate random float numbers with high precision, excluding zeros to ensure the randomness falls within the specified range.\n",
"4. **Continuous Capture and Analysis**: By continuously capturing audio and generating random numbers, we verify the randomness and plot the distribution, confirming the variability and unbiased nature of the generated numbers.\n",
"\n",
"Each run of the script produces a unique set of random numbers and a corresponding distribution graph, illustrating the reliability and effectiveness of using ambient noise for generating true random numbers. This method offers a practical and robust approach to achieving high levels of unpredictability, essential for enhancing security in various applications.\n",
"\n",
"By leveraging ambient noise, this approach ensures that the random numbers generated are truly random, thereby providing a secure foundation for cryptographic operations and other applications requiring high-quality randomness."
]
},
{
"cell_type": "markdown",
"source": [
"## Inspiration:\n",
"\n",
"* The **Business Security Enablement** chat is always a fun place to throw around ideas!!\n",
"* Special shoutout to Jeremy Triplett for the note on LSB extraction! (https://jeremytriplett06.medium.com/using-atmospheric-noise-to-generate-true-random-numbers-dc820ac9452d)"
],
"metadata": {
"id": "36Bk7oBDal23"
}
},
{
"cell_type": "code",
"source": [],
"metadata": {
"id": "sidbQ4lRftBs"
},
"execution_count": null,
"outputs": []
}
],
"metadata": {
"colab": {
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment