electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software » ChucK programming language
Beatslicing in ChucK
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [9 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
DrumAliens



Joined: Jul 10, 2008
Posts: 31
Location: UK
Audio files: 1

PostPosted: Thu Apr 16, 2009 2:32 pm    Post subject: Beatslicing in ChucK
Subject description: Beatslicing in ChucK
Reply with quote  Mark this post and the followings unread

I have written this program to allow me to try and come up with something a little more random when beatslicing drums.

The program takes a wav file and automatically works out the BPM of the original based upon the num_bars and num_beats defined in lines 9 and 10. It then creates random slices of the drum track based on the time signature defined by beat_num and beat_den in lines 21 and 22. It's currently set up to generate 2 bars of 4/4. By changing beat_num and beat_den you can set any time signature you wish (2/4, 3/4, 9/8, 11/8 etc).

For the beatsliced drumtrack I have increase the bpm a smidge (1% line 25) to try and reduce any crashes of beats. (I guess how successfully this is this will depend upon how much 'swing' there is in the drum track).

The way that I use it, is to take a drum track work out the number of beats and bars choose a time signature and then let the program do it's magic. When I get to something interesting I jot the numbers down and keep going till I get a collection. I can then program that into your DAW of choice (I use Renoise) and then compress, reverb and limit to your hearts content.

I still have to muck around to generate fills but it gives me something a little more different as a starting point.

Below is an example of the result making use of the attached wav file
http://www.freesound.org/samplesViewSingle.php?id=69875

Code:
// DrumAliens Paul

// ============================
// WAV File Information
// ============================
SndBuf buff => dac;
"F:/My Documents/My Music/Drum Loops/spinit.wav" => buff.read;

2   => int num_bar;
4   => int num_beats;
60.0*num_bar*num_beats*buff.freq() => float bpm;

// Sample point for a single beat
buff.samples()/(num_bar*num_beats) => float beat_step;

<<< bpm, beat_step  >>>;

// ============================
// Beat slice Information
// ============================
8 => int beat_num;
4 => int beat_den;

// Replay the WAV file a little faster to reduce the chance of glitches
1.01*bpm => float bpm_new;
<<< bpm_new >>>;

((1 / bpm_new) * 4.0)::minute => dur bar;
bar - (now % bar) => now;//sync to bar

// ============================
// WAV slice Information
// ============================

// Work out the break points based upon the number of bars and how the bar is split
int beat_ind[beat_den*num_bar];
// Set up
for (0=>int i; i < beat_ind.cap(); i++){
  i*beat_step $ int => beat_ind[i];
  <<< beat_ind[i] >>>;
 }

// Chose a number of slices from the WAV file
int beat_slice[beat_num];
for (0=>int i; i < beat_slice.cap(); i++){
  Std.rand2(0,beat_ind.cap()-1) => beat_slice[i];
  <<< beat_slice[i] >>>;
}

// An example
//3  => beat_slice[0];
//0  => beat_slice[1];
//5  => beat_slice[2];
//4  => beat_slice[3];
//1  => beat_slice[4];
//7  => beat_slice[5];
//1  => beat_slice[6];
//7  => beat_slice[7];

// Starting point for playing the WAV file
0 => int count;
beat_ind[beat_slice[count]] => buff.pos;

while(1) {

   (1.0/beat_den)::bar => now; //advance time by beat_den

   // Counter
   if (count >= beat_num-1){
      0 => count;}
     else {
      1 +=> count;
   }   
   
   // Work out the position in the WAV file
   beat_ind[beat_slice[count]] => buff.pos;
   
}


[url][/url]


spinit.wav
 Description:
spinit.wav used in the example code

Download (listen)
 Filename:  spinit.wav
 Filesize:  50.82 KB
 Downloaded:  603 Time(s)

Back to top
View user's profile Send private message
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 6221
Location: near Austin, Tx, USA
Audio files: 267

PostPosted: Fri Apr 17, 2009 5:44 am    Post subject: Reply with quote  Mark this post and the followings unread

sounds pretty dang kewl to me. keep us posted on your progress, please...
_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
DrumAliens



Joined: Jul 10, 2008
Posts: 31
Location: UK
Audio files: 1

PostPosted: Fri Apr 17, 2009 1:20 pm    Post subject: Reply with quote  Mark this post and the followings unread

Next step is to work out a way of increasing the BPM of a drum track.

The plan is to manually determine the points in a file where the drum hits are and then increase the BPM by maintaining the ratios between each of the drum hits. So the track still sounds like the original but faster. This can then be saved as a new WAV files and then beatsliced as before. (Might combine both of these two stages in one not sure at the moment).
Back to top
View user's profile Send private message
DrumAliens



Joined: Jul 10, 2008
Posts: 31
Location: UK
Audio files: 1

PostPosted: Thu Apr 23, 2009 2:28 pm    Post subject: Reply with quote  Mark this post and the followings unread

Step 1 completed. Though I have a question which I will come onto later.

Attached is version which allows you to play spinit.wav at a variety of different BPM's. Just adjust the value of bpm_new on line 19. (Going slower than the original BPM gives you get a reverb effect, try 150BPM for example).

Lines 26 to 40 give the points in the drum loop that I wanted alwys to play. The time between these sections is then altered based upon the ratio of bpm to bpm_new.

Code:
// DrumAliens Paul
 
// ============================
// WAV File Information
// ============================
SndBuf buff => dac;
 
"F:/My Documents/My Music/Drum Loops/spinit.wav" => buff.read;
 
2   => int num_bar;
4   => int num_beats;
60.0*num_bar*num_beats*buff.freq() => float bpm;
 
// ============================
// WAV slice Information
// ============================
 
// Define the new BPM
250 => float bpm_new;
//bpm => float bpm_new;
 
15 => int num;
int beat_slice[num];
float beat_time[num];
 
0       => beat_slice[0];
3455    => beat_slice[1];
5044    => beat_slice[2];
6611    => beat_slice[3];
9792    => beat_slice[4];
11459   => beat_slice[5];
12950   => beat_slice[6];
14715   => beat_slice[7];
16229   => beat_slice[8];
17801   => beat_slice[9];
19027   => beat_slice[10];
20984   => beat_slice[11];
22201   => beat_slice[12];
24384   => beat_slice[13];
25905   => beat_slice[14];
 
// Determine the time for a single sample
bpm/(bpm_new*buff.freq()*buff.samples()) => float inc_t;
 
//<<< inc_t >>>;
 
// Calculate the time in between slices
0.0 => float time_sum;
for (1=>int i; i < beat_slice.cap(); i++){
  (beat_slice[i] - beat_slice[i-1])*inc_t  =>  beat_time[i];
  beat_time[i] +=> time_sum;
}
 
// Check the new bpm
<<< bpm, 60.0*num_bar*num_beats/time_sum >>>;
 
// Starting point for playing the WAV file
0 => int count;
while(1) {
 
   // Work out the position in the WAV file
   beat_slice[count] => buff.pos;
   
   //Advance time to the next slice
   beat_time[count+1]::second => now; 
 
   // Counter 
   if (count >= beat_time.cap()-2){
      0 => count;}
     else {
      1 +=> count;
   }   
//       <<<count >>>;
}


The only problem is that you can end up with clicks as the new sections are spliced together, because they might not start at zero. Is there anyway that I can dynamically change the gain so that at the start of each new section you ramp up the gain rapidly to eliminate this effect ????

Thanks for any help
Back to top
View user's profile Send private message
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Fri Apr 24, 2009 1:21 pm    Post subject: Reply with quote  Mark this post and the followings unread

have a look at this, it might be of use to you.


breaking.ck
 Description:
Proof of concept break-cutting based on beat detection

Download (listen)
 Filename:  breaking.ck
 Filesize:  6.05 KB
 Downloaded:  523 Time(s)


_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
DrumAliens



Joined: Jul 10, 2008
Posts: 31
Location: UK
Audio files: 1

PostPosted: Fri Apr 24, 2009 2:10 pm    Post subject: Reply with quote  Mark this post and the followings unread

Kassen, thanks for that. This is going to keep me quiet for a while, whilst I pick my way through what's going on.

Just one question have you a link to the paper you mention.

Thanks
Back to top
View user's profile Send private message
DrumAliens



Joined: Jul 10, 2008
Posts: 31
Location: UK
Audio files: 1

PostPosted: Mon Apr 27, 2009 1:16 pm    Post subject: Reply with quote  Mark this post and the followings unread

Resolved my problem with the clicks by putting on a filter on the beginning and the end of any sections of WAV file that are played by attacking the Gain of SndBuf. The filter has a settling time of approximately 5ms which seems long enough to resolve the issue without destroying the original sound of the loop.

The filter should be able to handle any differences in sample times so hopefully it shouldn't need any further changes.

Hey I'm slowly getting the hang of this

Code:
// DrumAliens Paul

// ============================
// WAV File Information
// ============================
SndBuf buff => dac;

"F:/My Documents/My Music/Drum Loops/spinit.wav" => buff.read;

2   => int num_bar;
4   => int num_beats;
60.0*num_bar*num_beats*buff.freq() => float bpm;

// ============================
// WAV slice Information
// ============================

// Define the new BPM
350 => float bpm_new;

15 => int num;
int beat_slice[num];
float beat_time[num];

// Care points of the WAV file
0       => beat_slice[0];
3455    => beat_slice[1];
5044    => beat_slice[2];
6611    => beat_slice[3];
9792    => beat_slice[4];
11459   => beat_slice[5];
12950   => beat_slice[6];
14715   => beat_slice[7];
16229   => beat_slice[8];
17801   => beat_slice[9];
19027   => beat_slice[10];
20984   => beat_slice[11];
22201   => beat_slice[12];
24384   => beat_slice[13];
25905   => beat_slice[14];

// Calculate the sample rate in seconds
1.0/(buff.freq()*buff.samples()) => float Ts;

// Determine the time for a single sample
bpm/(bpm_new*buff.freq()*buff.samples()) => float inc_t;

// Calculate the time in between slices
0.0 => float time_sum;
for (1=>int i; i < beat_slice.cap(); i++){
  (beat_slice[i] - beat_slice[i-1])*inc_t  =>  beat_time[i];
  beat_time[i] +=> time_sum;
}

// Check the new bpm
<<< bpm, 60.0*num_bar*num_beats/time_sum >>>;

// Setup the Filter variables
0.0 => float yt => float yt_1;
1.0 => float ut;

// Filter Coefficients - will reach steady state in Tset seconds
0.005                          => float Tset;
Math.exp(-6.0*Ts/Tset) => float a1;
1.0-a1                         => float b0;

while(1) {

    // Advance through the parts of the WAV file
    for (0 => int count; count < beat_time.cap()-2; count++) {

        // Determine the time at the end this section
        now + beat_time[count+1]::second => time later;
        later - Tset::second                        => time decay;

        // Work out the position in the WAV file
        beat_slice[count] => buff.pos;
   
        // Reset the filter for the next section of the WAV file
        0.0 => yt_1;
   
        // Loop round each of the samples
        while (now < later){

            // Advance time by the WAV sample size
            Ts::second => now;

            // Calculate the 1st Order filter
            a1*yt_1 + b0*ut => yt;

            // Determine the direction of the input to the filter
            if (now > decay)
               0.0 => ut;
              else
               1.0 => ut;

            // Store the previous filter value
            yt => yt_1;

            // Use the filter output to control the output Gain
            yt => buff.gain;
        }
    }   
}

Back to top
View user's profile Send private message
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Mon Apr 27, 2009 4:04 pm    Post subject: Reply with quote  Mark this post and the followings unread

DrumAliens wrote:
Kassen, thanks for that. This is going to keep me quiet for a while, whilst I pick my way through what's going on.


You're welcome!

Quote:

Just one question have you a link to the paper you mention.


There is actually a series of papers;
http://www.informatics.sussex.ac.uk/users/nc81/research.php

Anything by Nick related to beat detection/ breakbeat-cutting/etc is worthwhile. You may also want to grab the "BBCut" library for SC and it's documentation if you're serious.

My implementation here is very simple, the main thing is that I start with analysis in order to preserve as much of the natural rhythmic characteristics of the original as possible while cutting. From there on I just shuffle the bits about while preserving their length. I should return to this as the treatment phase here is really quite simple and non-exciting, even though it does sound good from time to time.

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
DrumAliens



Joined: Jul 10, 2008
Posts: 31
Location: UK
Audio files: 1

PostPosted: Mon Apr 27, 2009 10:42 pm    Post subject: Reply with quote  Mark this post and the followings unread

Kassen, I will look into the papers
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [9 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » ChucK programming language
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use