I avoid reentrant code where possible because the SRAM is pretty tight and it is easy to run out, overwrite part of the stack, and fail mysteriously. I don't need that happening when some odd combination of interrupts occurs. That said, you could sei() inside your interrupt handler and that would allow a reentrant interrupt, hopefully not the one you are already handling.
I tend to use interrupts when precise timing is required, for instance if I am sending bits to modulate a radio and need the timing to be accurate I will program a timer to make a periodic interrupt at the right time. Or the USB handling code I use watches for the leading edge of the first bit with an interrupt.
Be aware: C and C++ interrupt handlers have something like a 70 clock cycle overhead to push the pop all the registers that are available to the API. If you are doing something small and very frequent you might want to do it in assembler o avoid that.
Aside from the two pin level interrupts, you need to go to the <avr/interrupt.h> functions to code the handlers. See avr-libc: <avr/interrupt.h>: Interrupts
For your application, I think you are sensing piano strings to see if they have been hit, I think polling would be best. You only have a couple of interrupts pins, so you'd still have to scan the strings looking for which one made the interrupt. Millisecond level accuracy is plenty for music, heck, I'm a bass player, you'd have to wait 20 milliseconds for the first cycle of my note to complete.
So, if you were using, say three 16:1 muxes your code might look like this...
for( int i = 0; i < 16; i++) { // going down to 0 would save 1 cycle/loop
digitalWrite( muxAddr0, i&1); // 5uS, note all three muxes are on the same address lines
digtialWrite( muxAddr1, (i>>1)&1); // 5uS, that way we can do the expensive addressing once
digitalWrite( muxAddr2, (i>>2)&1); // 5uS
digitalWrite( muxAddr3, (i>>3)&1); // 5uS
m[i] = digitalRead( mux0); // 5uS
m[i+16] = digitalRead( mux1); // 5uS
m[i+32] = digitalRead( mux2); // 5uS
}
You could scan 48 inputs in about 600 microseconds. Plenty fast for music. You will also need to budget some time for doing something with the data. If you are sending it back to the host over the serial port, then be aware the serial output functions are blocking. If a byte hasn't finished being sent then you will have to wait when you try to send the next one.
I suppose I could put an interrupt based serial output class into the playground. I use if for debugging when I don't want to disrupt the timing too badly. I haven't suggested putting it in the main code because you end up needing SRAM space for buffering which is in tight supply.