SOUND_TRACK_LOOP_COUNTER_TWO
The single web page application featured in this tutorial web page substantiates an audio track player which plays a natural number of MP3 sound tracks continuously (until the application web page is closed or refreshed). When the application user clicks the start button, the start and add buttons will disappear and the number of seconds elapsed since the start button was clicked will be displayed next to each sound track label along with that sound track’s respective file name and number of times that track was played (i.e. looped) on the application web page.
Note that an older and simpler version of the application featured on this web page is available at the following Uniform Resource Locator: https://karlinaobject.wordpress.com/sound_track_loop_counter/
Note also that the application which is featured on this web page is being hosted on karbytes’ own dark web server (as of 8:00AM Pacific Standard Time on 26_JANUARY_2025) and is usable via the Tor mobile and desktop browser (but, if using the mobile Tor browser, video and audio playing needs to be enabled in the browser settings). That application can be used to play one or more of the eleven MP3 files which are being hosted on the aforementioned server simultaneously inside of one browser tab and can be accessed using the following Uniform Resource Locator: http://qkbrwfubnh4knc6kkhx6uepccavpwezdf2al7w2quepe3qociegsi3yd.onion/KARBYTES_BLOG_APPS/SOUND_TRACK_LOOP_COUNTER_TWO/sound_track_looper_two.html
A video which serves as empirical evidence supporting the claim that the aforementioned .onion web page application is fully functional on the Tor browser application for Android operating system mobile devices is available at the following Uniform Resource Locator and features karbytes selecting and playing multiple sound tracks to play simultaneously (via one Tor browser tab) on its (Android) Galaxy A03s mobile device: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/sound_track_loop_counter_two_android_use_case_by_karbytes_26january2025.mp4
To view hidden text inside each of the preformatted text boxes below, scroll horizontally.
SOFTWARE_APPLICATION_COMPONENTS
Hyper-Text-Markup-Language_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/sound_track_looper_two.html
Cascading-Style-Sheet_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/karbytes_aesthetic.css
Cascading-Style-Sheet_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/bordered_container.css
JavaScript_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/sound_track_looper_two.js
To access the video files which each of the following audio files was derived from, visit the web page named SOUND_TRACK_LOOP_COUNTER_VIDEO_FILES on karbytes’ blogging website. That web page (which is external to this website) has been saved to the WayBack Machine and so have each of the raw video files hosted on GitHub web pages (and each of those GitHub-hosted raw video files is playable on the WayBack Machine saves of those GitHub-hosted raw video file web pages).
sound_file_1: https://github.com/karlinarayberinger/KARLINA_OBJECT_summer_2023_starter_pack/blob/main/coyote_vocalizations_01_july_2023.mp3
sound_file_3: https://github.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_1/blob/main/drums_karbytes_10_september_2023_part_0.mp3
sound_file_5: https://github.com/karlinarayberinger/KARLINA_OBJECT_summer_2023_starter_pack/blob/main/karbytes_guitar_13_may_2023.mp3
sound_file_6: https://github.com/karlinarayberinger/KARLINA_OBJECT_summer_2023_starter_pack/blob/main/karbytes_guitar_07_june_2023.mp3
sound_file_7: https://github.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_2/blob/main/karbytes_guitar_16_october_2023.mp3
sound_file_8: https://github.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_2/blob/main/karbytes_drums_20_october_2023.mp3
sound_file_9: https://github.com/karlinarayberinger/KARLINA_OBJECT/blob/main/guitar_karbytes_13july2024.mp3
sound_file_10: https://github.com/karlinarayberinger/KARLINA_OBJECT/blob/main/guitar_karbytes_20august2024.mp3
Hyper-Text-Markup-Language Code
The following Hyper-Text-Markup-Language (HTML) code defines the user interface component of the SOUND_TRACK_LOOPER_TWO web page application. Copy the HTML code from the source code file which is linked below into a text editor and save that file as sound_track_looper_two.html. Use a web browser such as Firefox to open that HTML file (and ensure that the JavaScript and Cascading-Style-Sheet files are in the same file directory as the HTML file).
(Note that angle brackets which resemble HTML tags (i.e. an “is less than” symbol (i.e. ‘<‘) followed by an “is greater than” symbol (i.e. ‘>’)) displayed on this web page have been replaced (at the source code level of this web page) with the Unicode symbols U+003C (which is rendered by the web browser as ‘<‘) and U+003E (which is rendered by the web browser as ‘>’). That is because the WordPress web page editor or web browser interprets a plain-text version of an “is less than” symbol followed by an “is greater than” symbol as being an opening HTML tag (which means that the WordPress web page editor or web browser deletes or fails to display those (plain-text) inequality symbols and the content between those (plain-text) inequality symbols)).
If copy-pasting the following HTML code from the preformatted text box below into a text editor, remove the zero-width space Unicode character (​) which is located between the ‘s’ and the ‘r’ in the script tag(s) which each link to a JavaScript file.
Hyper-Text-Markup-Language_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/sound_track_looper_two.html
<!-- /** * file: sound_track_looper_two.html * type: Hyper-Text-Markup-Language * author: karbytes * date: 26_JANUARY_2025 * license: PUBLIC_DOMAIN */ --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>SOUND_TRACK_LOOPER_TWO</title> <link rel="stylesheet" href="karbytes_aesthetic.css"> <link rel="stylesheet" href="bordered_container.css"> <style>#the_button { background: #00ff00; color: #000000; }</style> <style>#add_another_sound_file_menu_button { background: #ff9000; color: #000000; }</style> <style> #the_button:hover, #add_another_sound_file_menu_button:hover { background: #ffff00; color: #000000; } </style> <script src="sound_track_looper_two.js"></script> </head> <body onload="load_web_page()"> <div class="bordered_container"> <h1>SOUND_TRACK_LOOPER_TWO</h1> <p>Play one (or multiple) sound pattern(s) (whose duration(s) is(are) finite) for some indefinite number of cycles.</p> <p><em>(If you are experiencing this app via Tor on a mobile device, please ensure that audio is enabled in that browser's settings).</em></p> <p><em>(Note that there may be a delay of several seconds before a sound file is played due to network latency across the Tor network).</em></p> </div> <div class="bordered_container"> <p>1) Select one or multiple sound files from the list below.</p> <div id="sound_file_menu_area"> <p><select id="sound_file_menu_0"></select></p> </div> <p><input id="add_another_sound_file_menu_button" type="button" value="add_another_sound_file_menu()" onclick="add_another_sound_file_menu()"></p> <p>2) Click the start_sound_track_looper() button to start playing the selected sound file(s).</p> <p><input id="the_button" type="button" value="start_sound_track_looper()" onclick="start_sound_track_looper()"></p> </div> <div id="output" class="bordered_container"> <p><em>This section will be updated with information about selected sound tracks after the start button is clicked.</em></p> </div> <div class="bordered_container"> <p class="console" id="console_display">???</p> </div> </body> </html>
Cascading-Style-Sheet Code
The following Cascading-Style-Sheet (CSS) code defines a stylesheet which customizes the appearance of interface components of the SOUND_TRACK_LOOPER_TWO web page application. Copy the CSS code from the source code file which is linked below into a text editor and save that file as karbytes_aesthetic.css.
Cascading-Style-Sheet_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/karbytes_aesthetic.css
/** * file: karbytes_aesthetic.css * type: Cascading-Style-Sheet * date: 10_JULY_2023 * author: karbytes * license: PUBLIC_DOMAIN */ /** Make the page background BLACK, the text orange and monospace, and the page content width 800 pixels or less. */ body { background: #000000; color: #ff9000; font-family: monospace; font-size: 16px; padding: 10px; width: 800px; } /** Make input elements and select elements have an orange rounded border, a BLACK background, and orange monospace text. */ input, select { background: #000000; color: #ff9000; border-color: #ff9000; border-width: 1px; border-style: solid; border-radius: 5px; padding: 10px; appearance: none; font-family: monospace; font-size: 16px; } /** Invert the text color and background color of INPUT and SELECT elements when the cursor (i.e. mouse) hovers over them. */ input:hover, select:hover { background: #ff9000; color: #000000; } /** Make table data borders one pixel thick and CYAN. Give table data content 10 pixels in padding on all four sides. */ td { color: #00ffff; border-color: #00ffff; border-width: 1px; border-style: solid; padding: 10px; } /** Set the text color of elements whose identifier (id) is "output" to CYAN. */ #output { color: #00ffff; } /** Set the text color of elements whose class is "console" to GREEN and make the text background of those elements BLACK. */ .console { color: #00ff00; background: #000000; }
JavaScript Code
The following JavaScript (JS) code defines the functions which control the behavior of the SOUND_TRACK_LOOPER_TWO web page application. Copy the JS code from the preformatted text box below or from the source code file which is linked below into a text editor and save that file as sound_track_looper_Two.js.
JavaScript_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_28/main/sound_track_looper_two.js
/** * file: sound_track_looper_two.js * type: JavaScript * author: karbytes * date: 26_JANUARY_2025 * license: PUBLIC_DOMAIN */ let track_count = 1; // This global variable is used to keep track how many sound track file menus are added to the application user interface (and is 1 immediately after the page is loaded). /** * Dynamically add a new sound track menu to the application web page (and increment the global variable named track_count). * * Assume this function is called in response to the add_another_sound_file_menu() button being clicked. * * Also append a time-stamped message to the output DIV indicating when this function was called (assumedly by the add button being clicked). */ function add_another_sound_file_menu() { try { // Generate a time-stamped message string containing the (approximate) number of milliseconds which have elapsed since the Unix Epoch (i.e. 12:00AM Coordinated Universal Time on 01_JANUARY_1970). const message = "The add_another_sound_file_menu() button was clicked at time: " + generate_time_stamp(); let sound_file_menu_area = document.getElementById("sound_file_menu_area"); // Create a new paragraph (i.e. <p>) element. let new_paragraph = document.createElement("p"); // Create a new menu (i.e. <select>) element. let new_select = document.createElement("select"); new_select.id = "sound_file_menu_" + track_count; // Populate the <select> with menu options. new_select.innerHTML = get_menu_options(); // Append the <select> to the <p>. new_paragraph.appendChild(new_select); // Append the <p> to the menu area. sound_file_menu_area.appendChild(new_paragraph); // Increment the track count by one. track_count += 1; // Append a new paragraph element to the DIV element on the respective web page whose ID is "console_display". document.getElementById("console_display").innerHTML += (('<' + 'p' + '>') + message + ('<' + '/' + 'p' + '>')); } catch(e) { console.log("An exception to normal functioning occurred during the runtime of add_another_sound_file_menu(): " + e); } } /** * Extract the sound file portion from a Uniform Resource Locator (URL). * * @param {String} url - The full URL to the sound track file. * * @return {String} The sound file portion of the URL. */ function extractSoundFileName(url) { try { // Use the last index of '/' to find the start of the file name. const fileName = url.substring(url.lastIndexOf('/') + 1); return fileName; } catch (e) { console.error("An error occurred in extractSoundFileName:", e); return ""; } } /** * Get the Number of milliseconds which have elapsed since the Unix Epoch. * * The Unix Epoch is 01_JANUARY_1970 at midnight (Coordinated Universal Time (UTC)). * * @return {String} message displaying the time at which this function was called. */ function generate_time_stamp() { const milliseconds_elapsed_since_unix_epoch = Date.now(); return milliseconds_elapsed_since_unix_epoch + " milliseconds since midnight on 01_JANUARY_1970."; } /** * Generate an HTML formatted string which represents the list of OPTIONs displayed by a SELECT menu. * * By clicking on the SELECT element, a scrollable list of OPTIONs will appear. * * @return {String} a sequence of characters representing some natural number of OPTIONs inside of a SELECT menu. */ function get_menu_options() { let file_path_root = 'http://qkbrwfubnh4knc6kkhx6uepccavpwezdf2al7w2quepe3qociegsi3yd.onion/KARBYTES_BLOG_APPS/SOUND_TRACK_LOOP_COUNTER_TWO/'; let HTML_string = ''; // Define the list of sound eleven sound files and their display names. const sound_files = [ 'frogs_croaking_in_castro_valley_california_21_april_2022.mp3', 'coyote_vocalizations_01_july_2023.mp3', 'karbytes_drums_castro_valley_california_12_december_2022.mp3', 'drums_karbytes_10_september_2023_part_0.mp3', 'karbytes_guitar_castro_valley_california_12_december_2022.mp3', 'karbytes_guitar_13_may_2023.mp3', 'karbytes_guitar_07_june_2023.mp3', 'karbytes_guitar_16_october_2023.mp3', 'karbytes_drums_20_october_2023.mp3', 'guitar_karbytes_13july2024.mp3', 'guitar_karbytes_20august2024.mp3' ]; // Build the HTML string for each sound file sound_files.forEach((file, index) => { const selected = index === 0 ? ' selected' : ''; // Make the first option selected. HTML_string += `<option value="${file_path_root + file}"${selected}>${file}</option>`; }); return HTML_string; } /** * Return the value of the selected menu OPTION of a SELECT menu element. * * @param {String} select_menu_identifier is the identifier (id) of a SELECT HTML element. * * @return {String} the value of the selected menu OPTION. */ function get_selected_menu_option_value(select_menu_identifier) { try { let menu_object = {}, options_array = [], selected_option_index = 0, selected_option_object = {}, selected_option_value; menu_object = document.getElementById(select_menu_identifier); options_array = menu_object.options; selected_option_index = menu_object.selectedIndex; selected_option_object = options_array[selected_option_index]; selected_option_value = selected_option_object.value return selected_option_value; } catch(e) { console.log("An exception to normal functioning occurred during the runtime of get_selected_menu_option(select_menu_identifier): " + e); } } /** * Assume that this function is called whenever the web page file is opened or refreshed by a web browser. * * Display a time-stamped message which indicates the time at which the web page was opened as GREEN text inside the DIV at the bottom of the web page. * * Set the CYAN SPAN text which displays the number of seconds elapsed after the start_sound_track_looper() button is clicked to the value 0. * * Set the CYAN SPAN text which displays the number of times the selected audio track is played to the value 0. * * Populate the sound file SELECT menu with multiple sound file OPTIONs. * * Set the start_sound_track_looper() button to be visible rather than hidden to the application end user. * * If a runtime error occurs, use the try-catch block to perform exception handling by displaying a relevant web console message. */ /* function load_web_page() { try { const message = "The web page was loaded by the web browser at time: " + generate_time_stamp(); document.getElementById("console_display").innerHTML = message; document.getElementById("seconds_elapsed_display").innerHTML = "0"; document.getElementById("loops_completed_display").innerHTML = "0"; document.getElementById("sound_file_menu_0").innerHTML = get_menu_options(); document.getElementById("file_selected_display").innerHTML = get_selected_menu_option_value("sound_file_menu_0"); document.getElementById("the_button").style.display = "block"; } catch(e) { console.log("An exception to normal functioning occurred during the runtime of load_web_page(): " + e); } } */ /** * Assume that this function is called whenever the web page file is opened or refreshed by a web browser. * * Display a time-stamped message which indicates the time at which the web page was opened as GREEN text inside the DIV at the bottom of the web page. * * Set the CYAN SPAN text which displays the number of seconds elapsed after the start_sound_track_looper() button is clicked to the value 0. * * Set the CYAN SPAN text which displays the number of times the selected audio track is played to the value 0. * * Populate the sound file SELECT menu with multiple sound file OPTIONs. * * Set the start_sound_track_looper() button to be visible rather than hidden to the application end user. * * If a runtime error occurs, use the try-catch block to perform exception handling by displaying a relevant web console message. */ function load_web_page() { try { const message = "The web page was loaded by the web browser at time: " + generate_time_stamp(); const menuElement = document.getElementById("sound_file_menu_0"); if (menuElement) { menuElement.innerHTML = get_menu_options(); console.log("Menu populated successfully."); } else { console.error("Menu element not found during load_web_page()."); } document.getElementById("console_display").innerHTML = message; } catch (e) { console.error("An exception occurred in load_web_page():", e); } } /** * Assume that this function is called by the event of the start_sound_track_looper() button being clicked. * * Hide the add_another_sound_file_menu() button from the web page after that button is clicked. * * Hide the start_sound_track_looper() button from the web page after that button is clicked. * * Append a time-stamped message which indicates the time at which the button was clicked as green text to the DIV content at the bottom of the web page. * * Set the CYAN SPAN text which displays the number of times the each of the selected audio track is played to the value 0 (and increment by one each second after that indefinitely). * * Start playing the selected sound file(s) for an indefinite number of times and start incrementing the number of seconds elapsed and the number of times each sound track is played. * * If a runtime error occurs, use the try-catch block to perform exception handling by displaying a relevant web console message. */ function start_sound_track_looper() { try { const message = "The start_sound_track_looper() button was clicked at time: " + generate_time_stamp(); let sound_track_array = []; //let elapsed_seconds_display = document.getElementById("seconds_elapsed_display"); let output_display = document.getElementById("output"); let console_display = document.getElementById("console_display"); let add_button = document.getElementById("add_another_sound_file_menu_button"); let start_button = document.getElementById("the_button"); // Hide the buttons. add_button.style.display = "none"; start_button.style.display = "none"; // Reset the elapsed seconds display. //elapsed_seconds_display.innerHTML = "0"; // Clear the content which is initially displayed in the output display element (DIV). output_display.innerHTML = ""; // Loop through each track and set up the player. for (let i = 0; i < track_count; i++) { const menu_id = "sound_file_menu_" + i; const sound_file_name = extractSoundFileName(get_selected_menu_option_value(menu_id)); // Create an audio object for the track. const audio_file = new Audio(get_selected_menu_option_value(menu_id)); const loops_display_id = `loops_completed_${i}`; const elapsed_display_id = `elapsed_seconds_${i}`; // Add a track object for managing its data. sound_track_array.push( { sound_track_name: sound_file_name, loops_completed: 0, elapsed_seconds: 0, audio: audio_file, } ); // Create dynamic loop and elapsed displays for the track. const track_display_html = ` <p>* * *</p> <p>Sound Track: ${sound_file_name}</p> <p>Loops Completed: <span id="${loops_display_id}">0</span></p> <p>Seconds Elapsed: <span id="${elapsed_display_id}">0</span></p> `; // Replace the content which is displayed in the output DIV with the sound track data. output_display.innerHTML += track_display_html; if (i == (track_count - 1)) output_display.innerHTML += '<p>* * *</p>'; // Play the sound and start tracking loops and elapsed time audio_file.play(); setInterval(() => { const track_data = sound_track_array[i]; track_data.elapsed_seconds += 1; document.getElementById(elapsed_display_id).textContent = track_data.elapsed_seconds; if (audio_file.ended) { track_data.loops_completed += 1; document.getElementById(loops_display_id).textContent = track_data.loops_completed; audio_file.play(); // Restart the track } }, 1000); } console_display.innerHTML += `<p>${message}</p>`; } catch(e) { console.log("An exception to normal functioning occurred during the runtime of start_sound_track_looper(): " + e); } }
SOUND_TRACK_LOOP_COUNTER_TWO Interface (part_0)
The screenshot image below depicts what the SOUND_TRACK_LOOP_COUNTER_TWO web page interface could look like after that application is opened or refreshed in the web browser and before the user makes any changes to that web page application.
SOUND_TRACK_LOOP_COUNTER_TWO Interface (part_1)
The screenshot image below depicts what the SOUND_TRACK_LOOP_COUNTER_TWO web page interface could look like after the add_another_sound_file_menu() is clicked and before the start_sound_track_looper() button is clicked. The image also shows that some non-default sound files were selected from some of the sound file menus.
SOUND_TRACK_LOOP_COUNTER_TWO Interface (part_2)
The screenshot image below depicts what the SOUND_TRACK_LOOP_COUNTER_TWO web page interface could look like after the start_sound_track_looper() button is clicked.
(Note that, after the start_sound_track_looper() is clicked, the start_sound_track_looper() button and the add_another_sound_file_menu() button each disappear simultaneously so that the application user cannot change the sound track selection which is playing to some other configuration nor stop that ensemble which is playing nor change the speed at which any of its tracks is playing nor reverse the order in which auditory phenomena in any of those tracks is occurring as time elapses (but the user can reset the web page application by refreshing the web page)).
This web page was last updated on 19_FEBRUARY_2025. The content displayed on this web page is licensed as PUBLIC_DOMAIN intellectual property.