/** * @file hw4.ck * * @author Colin Sullivan * * Copyright (c) 2011 Colin Sullivan * Licensed under the MIT license. * * NOTE: All audio files used without permission. **/ /** * Define the overall structure of the piece as follows: * * |---------------------------------------------------| * t=0 t=totalDuration * * |---------------------------| * * Intro (51.8%) * * |------|------| * * Climax center: * (61.8%) * Climax width: * (20%) * * |---------| * * Ending (28.2%) **/ // Amount of audio channels 4 => int NUM_CHANNELS; // Total duration of piece 120::second => dur totalDuration; fun void record() { /** * Output dac to 4 mono sound files. **/ WvOut channelOuts[NUM_CHANNELS]; for(0 => int i; i < NUM_CHANNELS; i++) { channelOuts[i].wavFilename("output_"+i+".wav"); dac.chan(i) => channelOuts[i] => blackhole; } totalDuration + 10::second => now; for(0 => int i; i < NUM_CHANNELS; i++) { channelOuts[i].closeFile(); } } spork ~ record(); // Duration of intro 0.518*totalDuration => dur introDuration; // Time to start climax section now+introDuration => time climaxStartTime; // Duration of climax section 0.2*totalDuration => dur climaxDuration; // Time to start ending climaxStartTime+climaxDuration => time endingStartTime; // Duration of ending 0.282*totalDuration => dur endingDuration; // Time to end endingStartTime+endingDuration => time endTime; /** * Audio file sources **/ [ "recordings/Bounces/01-anything_but_marginal.wav", "recordings/Bounces/02-chilling_vision.wav", "recordings/Bounces/03-selling_no_value.wav", "recordings/Bounces/04-selling_to_willing_buyers.wav", "recordings/Bounces/05-so_we_may_survive.wav", "recordings/Bounces/06-I_understand.wav", "recordings/Bounces/07-economic_political_elites.wav", "recordings/Bounces/08-radical_rethinking_economics.wav", "recordings/Bounces/09-access_steady_employment.wav", "recordings/Bounces/10-richest_control_two_thirds.wav", "recordings/Bounces/11-really_prevents_average_joe.wav", "recordings/Bounces/12-banks_bailed_we_sold.wav", "recordings/Bounces/13-convinced_only_alternative.wav", "recordings/Bounces/14-too_big_fail_right.wav", "recordings/Bounces/15-federal_debt_long_deficit.wav", "recordings/Bounces/16-spending_more_taking.wav", "recordings/Bounces/17-moving_invisible_bridge.wav", "recordings/Bounces/18-cant_out_financial_debt.wav", "recordings/Bounces/19-freightens_me.wav", "recordings/Bounces/20-government_directly_influenced.wav", "recordings/Bounces/21-amount_wealth_staggering.wav", "recordings/Bounces/22-bottom_90_stagnated.wav", "recordings/Bounces/23-unlikely_parents_before.wav", "recordings/Bounces/24-not_country_but_world.wav", "recordings/Bounces/25-really_worries_me.wav", "recordings/Bounces/26-deep_suspicion_concentrated_power.wav", "recordings/Bounces/27-concentration_money_power_politics.wav", "recordings/Bounces/28-obvious_to_everybody.wav", "recordings/Bounces/29-funders_are_not_people.wav", "recordings/Bounces/30-forget_99_percent.wav", "recordings/Bounces/31-995_percent.wav", "recordings/Bounces/32-heres_what_we_all_believe.wav", "recordings/Bounces/33-very_powerful_financial_interests.wav", "recordings/Bounces/34-interests_not_public.wav", "recordings/Bounces/35-both_left_right_agree.wav", "recordings/Bounces/36-epicenter_money_politics.wav", "recordings/Bounces/37-one_place_symbolizes_wallstreet.wav", "recordings/Bounces/38-biggest_collapse_since_depression.wav", "recordings/Bounces/39-collapse_function_system_regulation.wav", "recordings/Bounces/40-alan_greenspan_mistake.wav", "recordings/Bounces/41-wallstreet_blackmail.wav", "recordings/Bounces/42-didnt_change_fundamental_problem.wav", "recordings/Bounces/43-many_people_more_at_risk.wav", "recordings/Bounces/44-terrify_everybody_left_right.wav", "recordings/Bounces/45-corporations_corrupt_reinforce_size.wav", "recordings/Bounces/46-critical_change.wav", "recordings/Bounces/47-america_more_unequal.wav", "recordings/Bounces/48-critical_change_bring_about.wav", "recordings/Bounces/49-so_much_money_district.wav", "recordings/Bounces/50-process_how_get_there.wav", "recordings/Bounces/51-large_protest_neighborhood.wav", "recordings/Bounces/52-growing_gap_system.wav", "recordings/Bounces/53-london_protests_going_on.wav", "recordings/Bounces/54-not_sustainable_system.wav", "recordings/Bounces/55-everyone_worried_global_recession.wav", "recordings/Bounces/56-hilarious_overthrow_government.wav", "recordings/Bounces/57-police_arrested_protestors.wav", "recordings/Bounces/58-frustrated.wav", "recordings/Bounces/59-income_inequality_greed.wav", "recordings/Bounces/60-building_awareness.wav", "recordings/Bounces/61-discharge_broader_responsibilities.wav", "recordings/Bounces/62-embrace.wav", "recordings/Bounces/63-minimum_president.wav", "recordings/Bounces/64-challenge_barak_obama.wav", "recordings/Bounces/65-tear_gas_bean_bags.wav", "recordings/Bounces/66-14_million_people_unemployed.wav", "recordings/Bounces/67-opportunities_not_come_back.wav", "recordings/Bounces/68-politics_corporations_into_ground.wav", "recordings/Bounces/69-restoration_middle_prosperity.wav", "recordings/Bounces/70-no_longer_ignored.wav", "recordings/Bounces/71-very_wide_support_agreement_us_pop.wav", "recordings/Bounces/72-end_up_local_pressures.wav" ] @=> string audioAll[]; dur audioDurationAll[72]; 01.552::second => audioDurationAll["recordings/Bounces/01-anything_but_marginal.wav"]; 01.167::second => audioDurationAll["recordings/Bounces/02-chilling_vision.wav"]; 03.250::second => audioDurationAll["recordings/Bounces/03-selling_no_value.wav"]; 05.000::second => audioDurationAll["recordings/Bounces/04-selling_to_willing_buyers.wav"]; 03.500::second => audioDurationAll["recordings/Bounces/05-so_we_may_survive.wav"]; 01.500::second => audioDurationAll["recordings/Bounces/06-I_understand.wav"]; 02.250::second => audioDurationAll["recordings/Bounces/07-economic_political_elites.wav"]; 02.875::second => audioDurationAll["recordings/Bounces/08-radical_rethinking_economics.wav"]; 03.250::second => audioDurationAll["recordings/Bounces/09-access_steady_employment.wav"]; 04.750::second => audioDurationAll["recordings/Bounces/10-richest_control_two_thirds.wav"]; 04.500::second => audioDurationAll["recordings/Bounces/11-really_prevents_average_joe.wav"]; 02.375::second => audioDurationAll["recordings/Bounces/12-banks_bailed_we_sold.wav"]; 03.625::second => audioDurationAll["recordings/Bounces/13-convinced_only_alternative.wav"]; 03.375::second => audioDurationAll["recordings/Bounces/14-too_big_fail_right.wav"]; 01.938::second => audioDurationAll["recordings/Bounces/15-federal_debt_long_deficit.wav"]; 01.625::second => audioDurationAll["recordings/Bounces/16-spending_more_taking.wav"]; 02.750::second => audioDurationAll["recordings/Bounces/17-moving_invisible_bridge.wav"]; 02.125::second => audioDurationAll["recordings/Bounces/18-cant_out_financial_debt.wav"]; 01.375::second => audioDurationAll["recordings/Bounces/19-freightens_me.wav"]; 03.375::second => audioDurationAll["recordings/Bounces/20-government_directly_influenced.wav"]; 04.500::second => audioDurationAll["recordings/Bounces/21-amount_wealth_staggering.wav"]; 02.375::second => audioDurationAll["recordings/Bounces/22-bottom_90_stagnated.wav"]; 04.125::second => audioDurationAll["recordings/Bounces/23-unlikely_parents_before.wav"]; 01.750::second => audioDurationAll["recordings/Bounces/24-not_country_but_world.wav"]; 01.024::second => audioDurationAll["recordings/Bounces/25-really_worries_me.wav"]; 02.750::second => audioDurationAll["recordings/Bounces/26-deep_suspicion_concentrated_power.wav"]; 03.125::second => audioDurationAll["recordings/Bounces/27-concentration_money_power_politics.wav"]; 01.271::second => audioDurationAll["recordings/Bounces/28-obvious_to_everybody.wav"]; 01.750::second => audioDurationAll["recordings/Bounces/29-funders_are_not_people.wav"]; 01.500::second => audioDurationAll["recordings/Bounces/30-forget_99_percent.wav"]; 02.625::second => audioDurationAll["recordings/Bounces/31-995::second;_percent.wav"]; 01.750::second => audioDurationAll["recordings/Bounces/32-heres_what_we_all_believe.wav"]; 02.250::second => audioDurationAll["recordings/Bounces/33-very_powerful_financial_interests.wav"]; 02.375::second => audioDurationAll["recordings/Bounces/34-interests_not_public.wav"]; 02.000::second => audioDurationAll["recordings/Bounces/35-both_left_right_agree.wav"]; 02.625::second => audioDurationAll["recordings/Bounces/36-epicenter_money_politics.wav"]; 05.750::second => audioDurationAll["recordings/Bounces/37-one_place_symbolizes_wallstreet.wav"]; 02.000::second => audioDurationAll["recordings/Bounces/38-biggest_collapse_since_depression.wav"]; 04.250::second => audioDurationAll["recordings/Bounces/39-collapse_function_system_regulation.wav"]; 02.625::second => audioDurationAll["recordings/Bounces/40-alan_greenspan_mistake.wav"]; 04.625::second => audioDurationAll["recordings/Bounces/41-wallstreet_blackmail.wav"]; 05.125::second => audioDurationAll["recordings/Bounces/42-didnt_change_fundamental_problem.wav"]; 03.500::second => audioDurationAll["recordings/Bounces/43-many_people_more_at_risk.wav"]; 02.500::second => audioDurationAll["recordings/Bounces/44-terrify_everybody_left_right.wav"]; 06.152::second => audioDurationAll["recordings/Bounces/45-corporations_corrupt_reinforce_size.wav"]; 01.750::second => audioDurationAll["recordings/Bounces/46-critical_change.wav"]; 03.125::second => audioDurationAll["recordings/Bounces/47-america_more_unequal.wav"]; 02.500::second => audioDurationAll["recordings/Bounces/48-critical_change_bring_about.wav"]; 04.125::second => audioDurationAll["recordings/Bounces/49-so_much_money_district.wav"]; 01.750::second => audioDurationAll["recordings/Bounces/50-process_how_get_there.wav"]; 02.000::second => audioDurationAll["recordings/Bounces/51-large_protest_neighborhood.wav"]; 05.125::second => audioDurationAll["recordings/Bounces/52-growing_gap_system.wav"]; 03.000::second => audioDurationAll["recordings/Bounces/53-london_protests_going_on.wav"]; 02.436::second => audioDurationAll["recordings/Bounces/54-not_sustainable_system.wav"]; 02.375::second => audioDurationAll["recordings/Bounces/55-everyone_worried_global_recession.wav"]; 13.000::second => audioDurationAll["recordings/Bounces/56-hilarious_overthrow_government.wav"]; 02.875::second => audioDurationAll["recordings/Bounces/57-police_arrested_protestors.wav"]; 01.002::second => audioDurationAll["recordings/Bounces/58-frustrated.wav"]; 02.083::second => audioDurationAll["recordings/Bounces/59-income_inequality_greed.wav"]; 01.197::second => audioDurationAll["recordings/Bounces/60-building_awareness.wav"]; 03.437::second => audioDurationAll["recordings/Bounces/61-discharge_broader_responsibilities.wav"]; 01.032::second => audioDurationAll["recordings/Bounces/62-embrace.wav"]; 03.146::second => audioDurationAll["recordings/Bounces/63-minimum_president.wav"]; 02.904::second => audioDurationAll["recordings/Bounces/64-challenge_barak_obama.wav"]; 03.479::second => audioDurationAll["recordings/Bounces/65-tear_gas_bean_bags.wav"]; 02.292::second => audioDurationAll["recordings/Bounces/66-14_million_people_unemployed.wav"]; 06.500::second => audioDurationAll["recordings/Bounces/67-opportunities_not_come_back.wav"]; 05.000::second => audioDurationAll["recordings/Bounces/68-politics_corporations_into_ground.wav"]; 02.396::second => audioDurationAll["recordings/Bounces/69-restoration_middle_prosperity.wav"]; 02.554::second => audioDurationAll["recordings/Bounces/70-no_longer_ignored.wav"]; 04.000::second => audioDurationAll["recordings/Bounces/71-very_wide_support_agreement_us_pop.wav"]; 04.875::second => audioDurationAll["recordings/Bounces/72-end_up_local_pressures.wav"]; [ "recordings/Bounces/01-anything_but_marginal.wav", "recordings/Bounces/02-chilling_vision.wav", "recordings/Bounces/03-selling_no_value.wav", "recordings/Bounces/04-selling_to_willing_buyers.wav", "recordings/Bounces/05-so_we_may_survive.wav", "recordings/Bounces/06-I_understand.wav", "recordings/Bounces/07-economic_political_elites.wav", "recordings/Bounces/10-richest_control_two_thirds.wav", "recordings/Bounces/11-really_prevents_average_joe.wav", "recordings/Bounces/12-banks_bailed_we_sold.wav", "recordings/Bounces/13-convinced_only_alternative.wav", "recordings/Bounces/14-too_big_fail_right.wav", "recordings/Bounces/15-federal_debt_long_deficit.wav", "recordings/Bounces/16-spending_more_taking.wav", "recordings/Bounces/17-moving_invisible_bridge.wav", "recordings/Bounces/18-cant_out_financial_debt.wav", "recordings/Bounces/19-freightens_me.wav", "recordings/Bounces/20-government_directly_influenced.wav", "recordings/Bounces/21-amount_wealth_staggering.wav", "recordings/Bounces/22-bottom_90_stagnated.wav", "recordings/Bounces/23-unlikely_parents_before.wav", "recordings/Bounces/24-not_country_but_world.wav", "recordings/Bounces/25-really_worries_me.wav", "recordings/Bounces/26-deep_suspicion_concentrated_power.wav", "recordings/Bounces/27-concentration_money_power_politics.wav", "recordings/Bounces/28-obvious_to_everybody.wav", "recordings/Bounces/29-funders_are_not_people.wav", "recordings/Bounces/30-forget_99_percent.wav", "recordings/Bounces/31-995_percent.wav", "recordings/Bounces/32-heres_what_we_all_believe.wav", "recordings/Bounces/33-very_powerful_financial_interests.wav", "recordings/Bounces/34-interests_not_public.wav", "recordings/Bounces/35-both_left_right_agree.wav", "recordings/Bounces/36-epicenter_money_politics.wav", "recordings/Bounces/37-one_place_symbolizes_wallstreet.wav", "recordings/Bounces/38-biggest_collapse_since_depression.wav", "recordings/Bounces/39-collapse_function_system_regulation.wav", "recordings/Bounces/40-alan_greenspan_mistake.wav", "recordings/Bounces/41-wallstreet_blackmail.wav", "recordings/Bounces/42-didnt_change_fundamental_problem.wav", "recordings/Bounces/43-many_people_more_at_risk.wav", "recordings/Bounces/44-terrify_everybody_left_right.wav", "recordings/Bounces/45-corporations_corrupt_reinforce_size.wav", "recordings/Bounces/46-critical_change.wav", "recordings/Bounces/47-america_more_unequal.wav", "recordings/Bounces/50-process_how_get_there.wav", "recordings/Bounces/51-large_protest_neighborhood.wav", "recordings/Bounces/52-growing_gap_system.wav", "recordings/Bounces/53-london_protests_going_on.wav", "recordings/Bounces/54-not_sustainable_system.wav", "recordings/Bounces/55-everyone_worried_global_recession.wav", "recordings/Bounces/57-police_arrested_protestors.wav", "recordings/Bounces/58-frustrated.wav", "recordings/Bounces/59-income_inequality_greed.wav", "recordings/Bounces/64-challenge_barak_obama.wav", "recordings/Bounces/65-tear_gas_bean_bags.wav", "recordings/Bounces/66-14_million_people_unemployed.wav", "recordings/Bounces/67-opportunities_not_come_back.wav", "recordings/Bounces/68-politics_corporations_into_ground.wav", "recordings/Bounces/72-end_up_local_pressures.wav" ] @=> string audioNegativeSentiment[]; [ "recordings/Bounces/08-radical_rethinking_economics.wav", "recordings/Bounces/09-access_steady_employment.wav", "recordings/Bounces/48-critical_change_bring_about.wav", "recordings/Bounces/49-so_much_money_district.wav", "recordings/Bounces/60-building_awareness.wav", "recordings/Bounces/61-discharge_broader_responsibilities.wav", "recordings/Bounces/62-embrace.wav", "recordings/Bounces/63-minimum_president.wav", "recordings/Bounces/69-restoration_middle_prosperity.wav", "recordings/Bounces/70-no_longer_ignored.wav", "recordings/Bounces/71-very_wide_support_agreement_us_pop.wav" ] @=> string audioPositiveSentiment[]; // Seed Std.rand2(0, 1); // Max volume (for now) 0.4 => float MAX_VOICE_VOLUME; /** * Play a random clip from the provided array of paths * through a random output channel. * * @param array The array of path names. **/ fun void play_random(string array[]) { play_random(array, SndBuf player); } fun void play_random(string array[], SndBuf player) { player => Gain g => dac.chan(Std.rand2(0, NUM_CHANNELS-1)); g.gain(MAX_VOICE_VOLUME); player.read(array[Std.rand2(0, array.size()-1)]); } fun void play_drone(time climaxStartTime, time endingStartTime, dur hilariousEndingQuoteDur) { 0.33 => float DRONE_MAX_VOLUME; // Low pitched oscillating drone SndBuf drone => BiQuad droneFilter; // gain for each channel Gain g[4]; droneFilter => g[0] => dac.chan(0); droneFilter => g[1] => dac.chan(1); droneFilter => g[2] => dac.chan(2); droneFilter => g[3] => dac.chan(3); g[0].gain(MAX_VOICE_VOLUME); g[1].gain(MAX_VOICE_VOLUME); g[2].gain(MAX_VOICE_VOLUME); g[3].gain(MAX_VOICE_VOLUME); // Play drone sound repetitively drone.loop(1); // set biquad pole radius .99 => droneFilter.prad; // set biquad gain .05 => droneFilter.gain; // set equal zeros 1 => droneFilter.eqzs; // our float 0.0 => float t; // Panning Rotator SawOsc rotate => blackhole; rotate.width(1.0); rotate.freq(0.125); rotate.phase(pi/4); // Not sure about this SawOsc recede => blackhole; recede.width(1.0); recede.freq(0.125); recede.phase(pi/4); drone.read("sfx/omonous-bass-hum-drone_loopable_48-16.aif"); while(now < climaxStartTime) { // droneFilter.freq(droneFilter.freq() + 100); // sweep the filter resonant frequency (recede.last()+1.0) * 2.0 => float dist; // 0.0 - 1.0 - 2.0 inside head, speaker circle, distant ((1+Math.sin(t))/2) => float sweepFactor; // Drone panning (rotate.last()+1.0)*0.5 => float theta; // 0.0 - 1.0 for full rotation Math.min(1.0, dist) => float distInside; for (0 => int i; i < NUM_CHANNELS; i++) { // TODO: Learn what this math is doing. Math.sin( Math.max(0.0, 1.0 - Math.fabs( Math.fmod( theta+0.5+(((NUM_CHANNELS-i) $ float) /NUM_CHANNELS), 1.0 ) - 0.5 ) * (NUM_CHANNELS*distInside) ) ) * (distInside/2.0+0.5) => float chanAmp; g[i].gain(chanAmp*DRONE_MAX_VOLUME); } sweepFactor * 1000.0 => droneFilter.pfreq; t + .01 => t; 10::ms => now; } // Higher pitched repeating drone SndBuf highDrone => PitShift pitch => BiQuad highDroneFilter; highDroneFilter => g[0]; highDroneFilter => g[1]; highDroneFilter => g[2]; highDroneFilter => g[3]; // set biquad pole radius .99 => highDroneFilter.prad; // set biquad gain .08 => highDroneFilter.gain; // set equal zeros 1 => highDroneFilter.eqzs; pitch.mix(1.0); pitch.shift(4.0); highDrone.loop(1); highDrone.read("sfx/omonous-bass-hum-drone_loopable_48-16.aif"); while(now < endingStartTime) { // Play low drone at a faster rate // sweep the filter resonant frequency (recede.last()+1.0) * 2.0 => float dist; // 0.0 - 1.0 - 2.0 inside head, speaker circle, distant ((1+Math.sin(t))/2) => float sweepFactor; sweepFactor * 1000.0 => droneFilter.pfreq; ((1+Math.sin(2.5*t))/2) => float highSweepFactor; highSweepFactor * 1500.0 => highDroneFilter.pfreq; // Drone panning (rotate.last()+1.0)*0.5 => float theta; // 0.0 - 1.0 for full rotation Math.min(1.0, dist) => float distInside; for (0 => int i; i < NUM_CHANNELS; i++) { // TODO: Learn what this math is doing. Math.sin( Math.max(0.0, 1.0 - Math.fabs( Math.fmod( theta+0.5+(((NUM_CHANNELS-i) $ float) /NUM_CHANNELS), 1.0 ) - 0.5 ) * (NUM_CHANNELS*distInside) ) ) * (distInside/2.0+0.5) => float chanAmp; g[i].gain(chanAmp*DRONE_MAX_VOLUME); } // Play higher drone at same rate t + .01 => t; 2.5::ms => now; } } // Leave time at end for hilarious ending quote audioDurationAll["recordings/Bounces/56-hilarious_overthrow_government.wav"] => dur hilariousEndingQuoteDur; spork ~ play_drone(climaxStartTime, endingStartTime, hilariousEndingQuoteDur); /** * Intro (0%) **/ <<< "Intro" >>>; false => int hitMax; while(now < climaxStartTime) { // The amount of time left until the climax starts (climaxStartTime-now) => dur leftUntilClimax; (leftUntilClimax/introDuration) => float introRemainingRatio; SndBuf player; // If we're past half of the introDuration if(introRemainingRatio < 0.5) { // Rarely, change playback rate if(Std.rand2f(0.0, 1.0) < 0.20) { // Either higher or lower if(Std.rand2f(0.0, 1.0) < 0.5) { player.rate(0.33); } else { player.rate(0.66); } } } // Play random negative sentiment sound, into a random channel play_random(audioNegativeSentiment, player); // Scale when to play next sound exponentially // http://www.wolframalpha.com/input/?i=log10%281-x%29%2B2+from+x+%3D+0+to+x+%3D+1 Math.log10(1-(1-introRemainingRatio))+2 => float scalar; scalar*(0.08*climaxDuration) => dur nextClipWaitDuration; // Scale when to play next sound linearly // introRemainingRatio*(0.2*climaxDuration) => dur nextClipWaitDuration; // If we're about to be playing a clip every 250ms, just let the others finish and wait for // climax to start. TODO: This might not work well with some durations, but I'm not sure. if(hitMax || nextClipWaitDuration < 250::ms) { true => hitMax; // Do not exceed 250ms 250::ms => now; } // If we're still above 250, keep triggering clips. else { nextClipWaitDuration => now; } } /** * Climax (51.8%) **/ <<< "Climax" >>>; while(now < endingStartTime) { // As the climax progresses, choose more and more positive quotes. Std.rand2f(0.0, 1.0) => float positiveOrNegativeQuote; // Ratio of climax progression (endingStartTime-now)/climaxDuration => float climaxCompleted; if(positiveOrNegativeQuote < climaxCompleted) { // Play positive quote play_random(audioPositiveSentiment); } else { // Play negative quote play_random(audioNegativeSentiment); } // Fire a clip every 250 - 1000ms Std.rand2f(250, 1000)::ms => now; } /** * Ending **/ <<< "Ending" >>>; while(now < endTime - hilariousEndingQuoteDur) { // Fire a positive clip play_random(audioPositiveSentiment); // Wait a variable amount of time, depending on how much time we've got left. 1 - ((endTime - hilariousEndingQuoteDur - now)/endingDuration) => float endingCompleted; (2000*endingCompleted)::ms => now; } // Load up hilarious ending statement SndBuf hilariousEndingQuote => Gain g => dac; g.gain(0.5*MAX_VOICE_VOLUME); hilariousEndingQuote.read("recordings/Bounces/56-hilarious_overthrow_government.wav"); hilariousEndingQuoteDur => now; <<< "Donezo" >>>;