Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

PYTHON ONLY Problem 1. (Ring Buffer ) Your first task is to model the ring buffer. Write a module ring_buffer.py that implements the following API:

PYTHON ONLY

Problem 1. (Ring Buffer ) Your first task is to model the ring buffer. Write a module ring_buffer.py that implements the following API: function description create(capacity) create and return a ring buffer, with the given maximum capacity and with all elements initialized to None capacity(rb) capacity of the buffer rb size(rb) number of items currently in the buffer rb is_empty(rb) is the buffer rb empty? is_full(rb) is the buffer rb? full? enqueue(rb, x) add item x to the end of the buffer rb dequeue() delete and return item from the front of the buffer rb peek(rb) return (but do not delete) item from the front of the buffer rb Since the ring buffer has a known maximum capacity, we implement it as a list (buff) of floats of that length, with the number of elements in the buffer stored in size. For efficiency, we use cyclic wrap-around, which ensures that each operation can be done in a constant amount of time. We maintain an index first that stores the index of the least recently inserted item, and an index last that stores the index one beyond the most recently inserted item. To insert an item into the buffer, we put it at index last and increment last. To remove an item from the buffer, we take it from index first and increment first. When either index equals capacity, we make it wrap around by changing the index to 0. The ring buffer can thus be represented as a list of four elements: the buffer (buff); number of elements (size) currently in buff; the index (first) of the least recently inserted item; and the index (last) one beyond the most recently inserted item. For example, the ring buffer shown in the figure below can be represented as the list [[, , 0.5, 0.3, -0.2, 0.4, , , , ], 4, 2, 6]. A ring buffer of capacity 10, with 4 elements Calling enqueue() on a full buffer should terminate the program with the message Error: cannot enqueue a full buffer. Calling peek() or dequeue() on an empty buffer should terminate the program with the message Error: cannot peek an empty buffer or Error: cannot dequeue an empty buffer. Use sys.exit(msg) to terminate a program with the message msg. $ python3 ring_buffer . py 10 Size after wrap - around is 10 55 $ python3 ring_buffer . py 100 Size after wrap - around is 100 5050 Problem 2. (Guitar String) Next, create a module guitar_string.py to model a vibrating guitar string. The module must implement the following API: 2 of 4 CS110 Project 3 (Guitar Sound Synthesis) Swami Iyer function description create(frequency) create and return a guitar string of the given frequency, using a sampling rate given by SPS, a constant in guitar_string.py create_from_samples(init) create and return a guitar string whose size and initial values are given by the list init pluck(string) pluck the given guitar string by replacing the buffer with white noise tic(string) advance the simulation one time step on the given guitar string by applying the Karplus-Strong update sample(string) current sample from the given guitar string Some details about the functions: create(frequency) creates and returns a ring buffer of capacity N (sampling rate 44,100 divided by frequency, rounded up to the nearest integer), and initializes it to represent a guitar string at rest by enqueueing N zeros. A guitar string is represented as a ring buffer of capacity N, with all values initialized to 0.0 create_from_samples(init) creates and returns a ring buffer of capacity equal to the size of the given list init, and initializes the contents of the buffer to the values in the list. In this assignment, this functions main purpose is for debugging and grading. pluck(string) replaces the N items in the ring buffer string with N random values between -0.5 and 0.5. tic(string) applies the Karplus-Strong update: deletes the sample at the front of the ring buffer string and adds to the end of the ring buffer the average of the first two samples, multiplied by the energy decay factor. sample(string) returns the value of the item at the front of the ring buffer string. $ python3 guitar_string . py 25 0 0.2000 1 0.4000 2 0.5000 3 0.3000 4 -0.2000 5 0.4000 6 0.3000 7 0.0000 8 -0.1000 9 -0.3000 10 0.2988 11 0.4482 12 0.3984 13 0.0498 14 0.0996 15 0.3486 16 0.1494 17 -0.0498 18 -0.1992 19 -0.0006 20 0.3720 21 0.4216 22 0.2232 23 0.0744 24 0.2232 Visualization Client The program guitar_sound_synthesis.py is a visual client that uses your guitar_string.py (and ring_buffer.py) modules to play a guitar in real-time, using the keyboard to input notes. When the user types the appropriate characters, the program plucks the corresponding string. Since the combined result of several sound waves is the superposition of the individual sound waves, the program plays the sum of all string samples. The keyboard arrangement imitates a piano key

""" ring_buffer.py

Models a ring buffer. """

import stdarray import stdio import sys

def create(capacity): """ Create and return a ring buffer, with the given maximum capacity and with all elements initialized to None. A ring buffer is represented as a list of four elements: the buffer (buff) itself as a list; number of elements (size) currently in buff; the index (first) of the least recently inserted item; and the index (last) one beyond the most recently inserted item. """

...

def capacity(rb): """ Return the capacity of the ring buffer. """

...

def size(rb): """ Return the number of items currently in the buffer rb. """

...

def is_empty(rb): """ Return True if the buffer rb is empty and False otherwise. """

...

def is_full(rb): """ Return True if the buffer rb is full and False otherwise. """

...

def enqueue(rb, x): """ Add item x to the end of the buffer rb. """

...

def dequeue(rb): """ Delete and return item from the front of the buffer rb. """

...

def peek(rb): """ Return (but do not delete) item from the front of the buffer rb. """

...

def _main(): """ Test client [DO NOT EDIT]. """

N = int(sys.argv[1]) rb = create(N) for i in range(1, N + 1): enqueue(rb, i) t = dequeue(rb) enqueue(rb, t) stdio.writef('Size after wrap-around is %d ', size(rb)) while size(rb) >= 2: x = dequeue(rb) y = dequeue(rb) enqueue(rb, x + y) stdio.writeln(peek(rb))

if __name__ == '__main__': _main()

""" guitar_string.py

Models a guitar string. """

import math import random import ring_buffer import stdarray import stdio import sys

# Sampling rate. SPS = 44100

def create(frequency): """ Create and return a guitar string of the given frequency, using a sampling rate given by SPS. A guitar string is represented as a ring buffer of of capacity N (SPS divided by frequency, rounded up to the nearest integer), with all values initialized to 0.0. """

...

def create_from_samples(init): """ Create and return a guitar string whose size and initial values are given by the list init. """

...

def pluck(string): """ Pluck the given guitar string by replacing the buffer with white noise. """

...

def tic(string): """ Advance the simulation one time step on the given guitar string by applying the Karplus-Strong update. """

...

def sample(string): """ Return the current sample from the given guitar string. """

...

def _main(): """ Test client [DO NOT EDIT]. """

N = int(sys.argv[1]) samples = [.2, .4, .5, .3, -.2, .4, .3, .0, -.1, -.3] test_string = create_from_samples(samples) for t in range(N): stdio.writef('%6d %8.4f ', t, sample(test_string)) tic(test_string)

if __name__ == '__main__': _main()

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions