联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-23:00
  • 微信:codinghelp

您当前位置:首页 >> C/C++编程C/C++编程

日期:2024-04-08 07:48

A4: Audio Streaming

1/16

A4: Audio Streaming

Due Sunday by 11:59p.m.

Points 200

Available after Mar 13 at 12a.m.

Last updated Apr. 2

WARNING: Please define any additional macros or functions using libas.h (.c), we may need to

override your particular as_*.h files for the automated testing, thank you!

Table of Contents

1. Introduction

1.1. Background

2. Basic Outline

2.1. Setup

3. Implementation

3.1. Passive Application Architecture

3.2. Active Application Architecture

3.3. Request Format

3.4. Dynamic buffering

4. Tasks

4.1 Server Tasks

4.2 Client Tasks

5. Grading scheme

6. Software you’ll probably need and some tips about how to proceed

6.1. Debugging the server or the client separately

6.2. Ensuring files received by the client match the server

6.3. Playing audio data (and how to install mpv)

6.3.1. Listening in the labs

6.3.2. Using real files

7. Updates and clarifications (check back here as needed)

8. Concluding remarks

1. Introduction

In this assignment, we will endeavor to develop a system of interconnected applications in one of the

most often-used and fundamental configurations: a server and accompanying client(s) connected

through sockets. This particular server will serve a small music (media file) library such that compatible

clients will be able stream the files on the server’s library, save the files locally, or both.

A4: Audio Streaming

2/16

In essence, streaming means that files can be requested from the server, and they are sent

progressively and intermittently in chunks. Your implementation will be able to support many different

media file types, including wav , mp3 , ogg , flac , etc.. The clients will use a dynamic buffer to receive

as many packets as are available, as they become available, before redirecting them to their appropriate

destination.

1.1. Background

For this assignment, multiple clients will be able to simultaneously stream available audio files from the

server. The client and the server will be using sockets to communicate with each other while transferring

text or binary data.

Roughly speaking, the server is responsible for 2 things:

1. Scanning and maintaining a “music library” – which for this assignment, will simply be maintaining a

list of files with correct extensions from a specified library directory (default: library/ ). See Section

6.3.2 to download a sample library that you may use to complete the assignment.

2. Listen for clients and handle clients in their own child process. The server will wait and retrieve the

exit status of all children under normal operation. Part of handling, is receiving and responding to

requests.

The client, on the other hand, will be responsible for:

1. Making requests and receiving responses

2. Managing an accompanying media player process named mpv (https://mpv.io/) , which is a free,

open source, and cross-platform media player. For installation information, please see Section 6.3

(https://q.utoronto.ca/#org2f62d44) .

2. Basic Outline

The majority of the design is provided to you in the starter code, and you are tasked with completing:

1. Server side processing of received requests and associated responses, for:

1. Listing all files

2. Streaming particular files

3. Setting up the server to listen on the specified port number

2. Client-side sending of requests and receiving responses, for:

1. Creating requests to list or stream files

2. Receiving files with dynamic buffering

3. Storing files as they are received

4. (Separately from local storing) Piping files to an accompanying audio (media) player process

The challenge in this assignment is ensuring that no bytes are lost, all bytes are transferred and received

in the right order, and this is done without memory errors, as well as feeling comfortable working with an

A4: Audio Streaming

3/16

already developed, and somewhat larger codebase. Throughout the starter code there are TODOs that

must be completed. The functions and structs defined in the three header files as_client.h as_server.h

and libas.h should not change, but you may add to these headers as you need, and change the values

of different macros.

2.1. Setup

Follow the instructions carefully, so that we receive your work correctly.

Your first step should be to log into MarkUs (https://markus.teach.cs.toronto.edu/2024-01/courses/16/) and

navigate to the A4 assignment. Then, at the bottom of the assignment page, click on the button labelled

"Add Starter Files to Repository".

Then, open a terminal on your computer and do a git pull in your existing CSC209 MarkUs repository.

Inside the repository, you should see a new folder name A4 containing the starter files for this

assignment.

Starter Files

as_server.c: contains code that implements the audio streaming server. You should modify this

file to complete the missing server features.

as_server.h: the header file for functions and structs that are defined and used in as_server.c. Do

not change.

as_client.c: contains code that implements the audio streaming client. You should modify this file

to complete the missing client features.

as_client.h: the header file for functions that are defined in as_client.c. Do not change.

libas.c: contains common code that are used by both the server and client. Do not change.

libas.h: contains the function prototypes and structs that are used by both the server and client. Do

not change.

stream_debugger.c: a simple debugging program that can help you with debugging your streaming

service. Do not change.

Makefile: a script that is used to simplify compilation of your program. Do not change.

Compilation

You should use the following command in your A4 folder to compile your source code:

make

If your submission does not compile, you will receive a mark of 0. If the compilation displays warning

messages, you will lose 10% of the total mark. It is your responsibility to ensure that your submission

works on teach.cs.

A4: Audio Streaming

4/16

Note that the Makefile will generate a file named port.mk which randomly assigns a default port number

for you. This is to minimize the chance where you and another classmate accidentally use the same port

number on teach.cs and negatively affect each other's work, e.g., if someone else is using your port

number, you won't be able to start the server.

After compilation, you can simply run the server as follows:

./as_server

Once the server is up and running, you can run the client to connect to the server:

./as_client

Note: while the starter code compiles, you will not be able to start the server until you complete the

following:

1. See Section 6.3.2 to set up your media library. Note: your server code does not need to handle an

empty library, so you need to make sure your library has at least one valid audio file.

2. The initialize_server_socket function.

If at any point, you are tired of the excessive debug output, you may re-compile your code in release

mode.

make clean

make release

Remember that debugger symbols are not available in release mode, so you will not be able to gdb your

program. Note that you will also need to run make clean before running make again to go back to debug

mode.

3. Implementation

A passive process is on a machine known as the “server”, somewhere on the network. This process is

bound to a particular port accompanying the network address for the machine.

3.1. Passive Application Architecture

The passive process’s main/original process sets up a socket for incoming connections and uses

select to manage whether clients are connecting, or if it locally receives 'q' on stdin , implying the

application should shut down. This is managed through the run_server function, which also re-scans the

library after a certain amount of iterations of it’s main loop. It also passively checks for the termination of

any existing child processes.

Each new connection is managed in a child process by (immediately calling) handle_client , which

receives the current layout of the library for the duration of the connection. It is responsible for receiving

A4: Audio Streaming

5/16

and responding to requests from the client.

Any requests to stream a file are written to the connected client in chunks of a maximum size:

STREAM_CHUNK_SIZE .

3.2. Active Application Architecture

The “client” application is a single active process anywhere on the same network as the “server”,

including the same machine. It features a small shell; see the client_shell function, featuring the

following commands:

1. list – to list the available files in the server’s library

2. get <index> – to save a particular file to client’s library directory

3. stream <index> – to stream a particular file without saving it

4. stream+ <index> – to stream a particular file and save it to the client’s library

5. help – to list the available commands

6. quit – to quit the application

These boil down to two types of requests:

1. listing the available files.

2. streaming a particular file.

The client will receive the library list and then be able to request a file to be streamed by it’s library index.

Commands 2-4 ultimately leverage stream_and_get_request with different arguments. This function will

also use select to accomplish interleaved and non-blocking: reading from the socket connection, writing

to the file-system and playing audio through the audio player. See Section 6.3, for more information on

how to stream the received files. The client must successfully wait for this process to terminate as

appropriate.

3.3. Request Format

List Request

To send a list request to the server, the client would send the following text data:

"LIST\r\n"

The server will respond with a list of files in the format index:filename, one file per line, in text format.

The list is returned as a single string with each file starting with an integer corresponding to it's index in

the library, in reverse order. A colon separates the index and the file's name. Each entry is separated by

a network newline "\r\n" (2 chars). For example, if the library contains the files "file1.wav",

"artist/file2.wav", and "artist/album/file3.wav" in this order, the data sent to the client will be the following

characters:

A4: Audio Streaming

6/16

For example:

"2:artist/album/file3.wav\r\n1:artist/file2.wav\r\n0:file1.wav\r\n"

Stream Request

To send a stream request to the server, the client would send a mixture of text and binary data. The text

data is exactly the following:

"STREAM\r\n"

and a 4-byte binary data should follow, that represents the requested file index. For example, to stream

file index 3, a full packet will look like this in hex:

5354 5245 414d 0d0a 0000 0003

S T R E A M \r\n |-- 3* -|

*3 is in 32-bit big endian byte order.

Note that the file index needs to be in network byte order, i.e., big endian byte order.

If the file index exists, the server will respond by first sending the size of the file in network byte order,

then sending a series of data chunks in the following format:

[-- size of file --][ ----- data chunk 1 -----][ ----- data chunk 2 -----][ -- last data chunk -- ]

<---- 4 bytes -----><------ 1024 bytes -------><------ 1024 bytes -------><-- up to 1024 bytes --->

Note that the last chunk of data is can be less than 1024 bytes. For example, suppose the you send a

text file with the content "hello world" using this protocol, the server response will look like this in hex:

0000 000b 6865 6c6c 6f20 776f 726c 64

|- 11 --| h e l l o _ w o r l d

Hint: 0x0000000b is the decimal 11 in big endian, which is the size of the file.

3.4. Dynamic buffering (client-side)

First thing that you’ll need to take a look at is the realloc function documentation. Have a quick read of

man realloc .

The intended dynamic buffer is as follows, and shall receive full marks if successfully accomplished.

Marks for alternative solutions will be subject to TA discretion. The simplest of which is a fixed size array

on the stack (or the heap*), and this will receive 1/3 of the buffering grade, even if everything else is

perfect. The keyword here is dynamic, so the realloc function will probably be your friend. Any solution

that does not implement dynamically changing buffer sizes on the client can achieve a maximum grade,

of at most, 90% on this assignment overall (only a third of the 15% awarded for dynamic buffering,

because technically any non-static buffer is kind of dynamic).

A4: Audio Streaming

7/16

The intended/aspirational implementation features two buffers: one to read directly from the socket --

which will be of a fixed size ( NETWORK_PRE_DYNAMIC_BUFF_SIZE ) allowing at most this many bytes to be read

from the socket each time select indicates it is ready. Then, a second and dynamic buffer to hold all the

bytes that have been received by the client, but not yet been written to (both) the audio process pipe and

library file (as needed). This includes what was read into the first buffer, and any bytes that you have no

managed to write to the other targets yet. If the byte hasn’t been written out to each fd (or one of them if

not doing stream+) yet, it should be held in this second buffer that dynamically grows, so that the first

can read from the network again. All bytes from the first fixed buffer move through the second dynamic

one.

The first bytes of the dynamic buffer shall contain the next bytes that need to be written. So, upon

reading the first, say, four bytes from the server, in your first fixed buffer, you then make your dynamic

buffer 4 bytes in size and move those bytes into the second buffer in the order they were received.

As more bytes are received from the network, your second buffer should expand to contain the additional

bytes. “Simultaneously”, you should be writing to one or both of the audio and file destinations, starting

from the beginning of the buffer. It is sufficient to simply try to write the entire contents of the buffer to

either stream when they are ready for writing. But, this doesn't guarantee that they well all be, in fact,

written. Use the return value of write to get the number of bytes actually written, to update which byte

each stream (audio or file) will need next for an unbroken stream of data.

Once you’ve finished writing data out of the second buffer, you can look to see how many of the first

bytes in the buffer are no longer needed, as in, ones that have already been written to both (for stream+ ,

otherwise it is either) the audio and file streams. You should then resize your buffer so that it no longer is

taking up memory for those bytes. So if your dynamic buffer had 100 bytes in it, and you wrote 20 bytes

to the audio process and 15 bytes to the local library file, you can remove 15 bytes from the buffer,

making a new buffer of 85 bytes in length. Somehow, the audio process must still start from the correct

byte offset in this example, so it will be "ahead" of the local file.

Note that the server should be sending the file’s bytes starting with the first byte in the file, and

ending with the last, even though network-byte-order is big-endian. Endianess pertains to

contiguous data-types, not files or streams of bytes.

How do you accomplish this “simultaneously”? Well we will use select , and read from the network if

select indicates that the connected socket has bytes to be read, and write to either file descriptor if it

indicates that either file descriptor can be written to. Then use select again in a loop.

*Allocated once and free'd once. Allocating and freeing multiple times for one file transfer/stream will be

considered dynamic, but only the described solution is guaranteed full marks. Any other dynamic

solutions will receive at least 50% (7.5/15) and up to 100% (15/15) for this portion of the work.

4. Tasks

A4: Audio Streaming

8/16

For each function listed below, there are descriptions of the expected functionality above the function

signature in the header files, or above the function body for helper functions. You should consult them for

more information on how to implement each function. Hint: there are some helper functions that have

already been implemented for you to simplify some tasks. Please take some time to understand how

they work.

For each function, there is a list of errors that you must handle. If any of the listed error occurred,

print a relevant error message (not tested but the TA will look at it) then return -1 (tested). If you

have temporarily-allocated resources (e.g., heap memory, file descriptors), you need to free/close

them before returning.

General set of errors you must always handle for all functions:

Reading or writing to socket failed.

Memory allocation, e.g., malloc , failed.

4.1. Server Tasks

For the server, you are responsible for implementing the following functions:

initialize_server_socket

int initialize_server_socket(int port)

The purpose of this function is to initialize a server socket up to the point of listening for connections. You

should use the existing helper functions to complete this task. On success, return the file descriptor used

for listening to connections.

Hints:

You should be calling init_server_addr and set_up_server_socket to complete this function. Take

some time to learn what they do.

For set_up_server_socket , use MAX_PENDING for the num_queue argument.

list_request_response

int list_request_response(const ClientSocket * client, Library *library)

The purpose of this function is to respond to the client request for listing the files in your media library.

See Section 3.3 for more information. You should take a look at the Library struct definition in libas.h ,

and understand the purpose and format of each member variable.

Advices:

Take a look at _free_library in libas.c and make sure you understand the data structure. Then,

take a look at scan_library in as_server.c and make sure you understand how the object is

initialized.

Use the write_precisely function to simplify writing to socket.

You may assume filenames do not include newline characters.

A4: Audio Streaming

9/16

You may assume the media library is never empty.

Hence, you need to ensure there is at least one audio file in your library folder, otherwise the

server will not send any response and the client will hang.

stream_request_response

int stream_request_response(const ClientSocket * client, Library *library, uint8_t

*post_req, int num_pr_bytes)

The purpose of this function is to respond to the client request for streaming a particular file.

The file is streamed in chunks of maximum STREAM_CHUNK_SIZE bytes. The client will be able to request a

specific file by its index in the library. Please see Section 3.3 for more information.

It is important to understand the post_req and num_pr_bytes parameters, because there is no guarantee

whether the file_index data from the client is included in the request packet, or would come afterwards.

This could happen:

# only 1 byte out of the 4 bytes for file_index came with the stream request

"STREAM\r\n" + 0x00

The post_req parameter is a pointer to the end of the stream request data (after the \r\n ), and

num_pr_bytes tells you how many bytes of data are available in post_req . In the above example,

num_pr_bytes would be 1.

To successfully complete this function, you must look at num_pr_bytes and determine how many more

bytes you need to read from client_socket . If num_pr_bytes is 4, then you don't need read anymore.

After you have the 4-bytes of data, you need to convert it from network byte order back to native byte

order so that the value is correct. Hint: use ntohl .

Errror Handling:

If any of the following error occurred, print a relevant error message (not tested but the TA will look at it)

then return -1 (tested). If you have temporarily-allocated heap memory, you need to free it before

returning.

The file index does not correspond to a valid media file, i.e., index out of range. (unfortunately, this

will cause the client to hang, but it indicates that you sent an invalid request).

Requested file does not exist (this can happen if someone deleted the file and your server hasn't

realized it yet).

num_pr_bytes is greater than 4 (think time: why is this an error?)

4.2. Client Tasks

For the client, you are responsible for implementing the following functions:

get_library_dir_permission

A4: Audio Streaming

10/16

int get_library_dir_permission(const char *library_dir, mode_t * perpt)

Given the name of the library folder library_dir , return its permission through the output parameter

perpt . If library_dir does not exist, create it with the permission 0700 . On success, return 0. You may

assume perpt is never NULL .

Hint: you will need to use the stat system call and mkdir system system call.

Error Handling:

Any of the system calls you made failed.

Except in the case where the first time you call stat , the library folder does not exist.

list_request

int list_request(int sockfd, Library *library)

Send a list request (please see Section 3.3) to the server and store the list of available audio files in the

library object. Upon success, print the list of audio files by their file_index in ascending order, and return

the number of files available in the library, e.g.:

0: flac/teenage-ant-marching-band.flac

1: m4a/atmospheric-eerie-song.m4a

2: m4a/night-sessions.m4a

3: mp3/dark-evil-piano.mp3

4: mp3/encryption.mp3

5: mp3/im-your-dj.mp3

6: ogg/permsound.ogg

7: ogg/rainbow-disco-bears.ogg

8: wav/ac-guitar.wav

9: wav/afx-study.wav

10: wav/cha-cha-ender.wav

11: wav/magic-harp.wav

12: wav/wedidit.wav

13: wav/weird-synth.wav

Use the following format specifier to print each line to standard output: "%d: %s\n" .

Advices:

Take a look at _free_library in libas.c and make sure you understand what is heap-allocated and

what isn't. Then, take a look at scan_library in as_server.c and make sure you understand how the

object is initialized. You can re-use some of the logic to implement this function, e.g., instead of

reading from the file system, you are reading and parsing the response packet from the server.

Most of the response packet parsing is done for you in the function get_next_filename . Learn how to

use the function.

Error Handling:

get_next_filename failed.

start_audio_process

A4: Audio Streaming

11/16

int start_audio_player_process(int *audio_out_fd)

Create the audio player process, and redirect standard input to it. Use the AUDIO_PLAYER and

AUDIO_PLAYER_ARGS macro constants for setting up arguments to exec .

Notes:

Because the audio player process sometimes takes a while to boot up, you should sleep for

AUDIO_PLAYER_BOOT_DELAY seconds.

If you are using WSL, the executable name will be "mpv.exe" instead of just "mpv". You can deal with

this discrepancy by temporarily changing the macro AUDIO_PLAYER (defined in as_client.h ) from

"mpv" to "mpv.exe". However, do not check this change in.

Error Handling:

Any of the system calls you made in the parent process failed.

send_and_process_stream_request

int send_and_process_stream_request(int sockfd, uint32_t file_index, int audio_out_fd, int

file_dest_fd)

This is the meat of this assignment. The purpose of this function is to simultaneously receive data from

the server, save data to a file, and steam data to the audio process. You are required to use select to

accomplish this feat. Failure to use select will result in 0 for this function.

Please see Section 3.3 for information on how to send a stream request packet, and what the server

response looks like.

Before returning from this function (failure or success), you must close the two file descriptors,

audio_out_fd and int file_dest_fd .

Advices:

Because an audio file can be extremely large (e.g., 4GB), it would be infeasible to preallocate a

buffer for the entire incoming file. Therefore, you need create a dynamic buffer for receiving data and

writing data to one or both file descriptors. Please see Section 3.4 for more information on how to

implement this. However, you may create the entire buffer in memory just as a intermediate step to

get things working, before attempting dynamic buffering.

Use the timeout macro constants for setting up select 's timeout argument: SELECT_TIMEOUT_SEC and

SELECT_TIMEOUT_USEC .

Error Handling:

Both file descriptors, audio_out_fd and int file_dest_fd , are invalid, i.e., -1.

If you receive more data than what the specified file size is, print an error message (not auto-tested,

but we will look at your code) and disregard the extra bytes (do not return -1).

A4: Audio Streaming

12/16

5. Grading scheme

The following is a breakdown of the grading scheme for this assignment:

10% style

30% memory management (valgrind testing)

15% server/client each

20% server functionality

25% client functionality (independent of dynamic buffer)

15% Implementation (TA inspection) of client-side buffering

Max 5% if not dynamic

6. Software you’ll probably need and some tips about

how to proceed

6.1. Debugging the server or the client separately

The basic utility known as netcat or nc (see man nc ) is ideal for sending or receiving raw text

(amongst other things with some work). You can use nc to setup a dummy server that you can view

requests with, and type back responses to your client (locally on your machine, bound to port 3456) like

this:

nc -v -C -l -p 3456

This sets up verbose printing, network newlines to be sent everytime you hit enter ( \r\n not just \n ,

notice that our requests make use of this), and listening – essentially a passive network process.

You can configure an active netcat process as follows, more commonly referred to as a client to connect

to this server with:

nc -v -C localhost 3456

Try running both, in seperate terminals, side-by-side and start entering data into either side. Notice how it

pops up in the other terminal. Once you get your client or server implementations working, you can swap

out one of these netcat programs for your solution, e.g. connect your as_client to an nc server.

Note, you can also run the server on teach.cs, and then connect by replacing localhost with

teach.cs.utoronto.ca, then you can run the server after ssh'ing into teach.cs, and the client locally or on

teach.cs, and connect to the server that is running on teach.cs!

I recommend implementing the server first, since a lot of heavy lifting has already been done for you in

this application. Then you can try running something like this before implementing the client, to see that it

is possible:

A4: Audio Streaming

13/16

echo -e "STREAM\r\n\x00\x00\x00\x02" | nc -C <server-address> <port> | dd bs=1 skip=4 | tee filenam

e.wav | mpv -

This should allow you to retrieve the file with index 2 (notice the last of 4 hex bytes is 0x02 in the echo

message) from the server, skip the first 4 bytes of response (the file’s size as an unsigned int sent by the

server), save it to filename.wav and play it through mpv . This solution may not produce a perfect

filename.wav depending on how you kill the line of commands. But, in effect, the client’s most difficult

task can be accomplished through this line of shell script with fairly standard programs. Nonetheless we

are going to do the dynamic buffering as an exercise and a demonstration of how one might buffer

media. The portion of \x00\x00\x00\0x02 above, indicates 4 hexadecimal numbers. Network byte order

is big-endian, so the above is the number two, expressed as a 32-bit big-endian integer.

6.2. Ensuring files received by the client match the server

The command line utility diff will report when two files differ, so use this to check that the received file

is the same as the one on the server. If they are identical, it will print nothing! Alternatively cmp also

provides good output. These are sufficient tools, but are hard to use for binary files. Remember that you

can send and recieve (though not actually play anything through mpv) any file data you like, as long as

the extension is compatible (see libas.h). This means you can debug with files containing only ASCII text

in them, and use diff tools like diff or cmp, or diff within your IDE to see where things went wrong.

While you are working on receiving files, changing the size of buffers, or more specifically, the number of

bytes you read or write at once, will help debug the process of sending and receiving data. Stepping

through your code with smaller buffers and test files will really help.

As a starting point, it may be helpful to create a dummy file in text format to test that file transfer is

working. You will need to rename the file to have the extension .wav , otherwise the server will not pick it

up. You should use the get command on the client to attempt transferring the file.

6.3. Playing audio data

To actually hear the output of the audio files (video files were not tested, I suspect you might need to

enlarge some of the buffers for performance reasons, but it should probably work too, see

SUPPORTED_FILE_EXTS and let me know on Piazza if you looked into it), you’ll be piping data into software

that can decode any compression used to store the file and then relay the correct data to the audio driver

system. The driver system is not consistent between Linux, Mac and Windows, so we will use the mpv

(https://mpv.io/) project to do all this work in a cross-platform way, and allow us to experiment using

files with arbitrary compressions/encodings/extensions (not all of which are compatible with streaming,

but .mp3 and .mp4 containers should represent stuff that will work if you get this far). Note that you can

use mpv's controls when you've exec'd the process (try using the arrow keys while music is playing).

tldr: A good first step overall is installing mpv . You can use mpv to play media files directly through

stdin by giving it the argument - , as in mpv -

A4: Audio Streaming

14/16

On the teach.cs machines, the basic command aplay is sufficient to process .wav files, and is a good

starting place if you need to limit output, but you should have access to mpv on the teach.cs machines

as well, and this will give you some consistency across platforms. Install mpv on your local machine,

make sure it is accessible “via command line” (i.e. it’s on your PATH ) and then switch to the mpv -specific

macros in as_client.h .

Most linux package managers provide mpv e.g. sudo apt install mpv but note if you're using the

windows linux subsystem (WSL), you're probably better off installing mpv outside of the linux subsystem

and linking to the executable (the application called mpv in the installation) on a correct path to be

accessible to a bash terminal in WSL. It will take some digging to figure out. This github repo

(https://github.com/jnozsc/mpv-nightly-build) hosts mac builds, and is linked to from mpv's main

installation page. You'll still need to be able to access mpv from your shell's path.

While this will be great when everything is working, we’ve also included the code for something called

stream_debugger , which will help you debug what you are sending to the external process and when.

6.3.1. Listening in the labs

Please avoid disturbing others with playing any audio out of the speakers in the lab. There are

headphone jacks on the lab machines, on the front of the desktop box (top jack is only microphone,

bottom is headphones with optionally connected mic, use this with standard headphones):

As well as an audio out (green; largely equivalent to the headphones, but perhaps slightly different

voltages for additional amplification) on the back of the desktop box:

A4: Audio Streaming

15/16

6.3.2. Using real files

We have made a small library of free sounds for your testing (downloaded from https://freesound.org/

(https://freesound.org/) ). You can get a zipped copy here

(https://q.utoronto.ca/courses/337029/files/31062827?wrap=1)

(https://q.utoronto.ca/courses/337029/files/31062827/download?download_frd=1) . You should unzip this file

in the A4 folder. Make sure the library folder is created after unzipping. WARNING: do not check in

the audio files into your repository. We have add a .gitignore file to make sure you do not

accidentally make this mistake.

If you are working on the teach.cs machine, you can also make a copy of the audio library from our

course directory:

# you should be in your A4 folder

cp -R /u/csc209h/winter/pub/a4/library .

You can also check out this article (https://creativecommons.org/about/arts-culture/arts-culture?resources/legalmusicforremixing/) for a bunch of free choices to add to your library, ccMixter had some

fun things.

7. Updates and clarifications (check back here as

needed)

Mar 20, 5:31pm PST (jsun): updated starter code and solution to be more const-correct. Removed

the need to implement get_file_request , stream_request , and stream_and_get_request for the starter

code.

Mar 24, 7:47pm PST (jsun): updated handout to clarify that you may assume the server's media

library is never empty.

A4: Audio Streaming

16/16

Apr 1, 12:45pm EST (dee): Warning pertaining to avoiding adding to as_client.h and as_server.h.

Use libas.h and libas.c for any macros or additional functions that need to be accessible across

multiple .c files.

Apr 2, 1:28pm EST (dee): There was some concern that the above meant that you could not change

macro values, particularly AUDIO_PLAYER and/or AUDIO_PLAYER_ARGS in as_client.h. You can and should

have fun changing all the macros as you like, but your solution will be tested using the values from

the starter, as well as some additional values of AUDIO_PLAYER and AUDIO_PLAYER_ARGS to use a

testing executable for testing the bytes going to the audio player process.

Apr 2, 1:46pm EST (dee): I've made a variety of references to our dynamic buffer being a circular

buffer. This is not a conventional use of this term bizzare use of a term I frankly have been otherwise

familiar with: circular buffers tend to refer to buffers of a fixed size that write over the beginning of a

buffer when they are filled (and then write in a circle). My usage of the term is based in circles being

a useful expression of a line with infinite length and multiple entry/exit points and a general

disposition towards using circular models over more linear dimensions.

8. Concluding remarks

This has been one of the most impressive instances of CSC209 in my memory, all things considered.

This is understood to be a difficult course, and even making it through to the point of reading the end of

this document should be understood as an accomplishment.

As you complete this assignment savour your new knowledge and pat yourself on the back. Well done.


相关文章

版权所有:留学生编程辅导网 2020 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp