চেতনা thinking fast and slow

থিংকিং fast and স্লো আর চেতনার সম্পর্ক 
Kahneman tversky নোবেল পেয়েছেন 
এই বলে যে মানুষ এর system 1 হচ্ছে চিন্তা না করে কাজ করার মাইন্ড 
সিস্টেম 2 হচ্ছে গভীর চিন্তা করে কাজ করার mind 
যেকোন একটা বিষয় কে  লিখে বোঝাতে না পারলে সেই বিষয়ের উপর চেতনা সম্ভব নয়। সিস্টেম 2 জাগিয়ে রেখে চলতে হবে সমস্ত মাইক্রো second এর সমস্ত একটিভিটি তে।

সিস্টেম 2 টা প্রায় কেউ কাজে লাগায় না।
প্রত্যেক টা ধাপ না লিখে করলে সিস্টেম 2 active হয় না কোনদিন। যা কিছু চিন্তা করছেন লিখুন। ছবি আঁকুন। যা কিছু বলছেন ভথবা ভাবছেন সেইটা লিখুন এবং ছবি আঁকুন। গ্রাফ থিওরী সাজিয়ে lpp সাজিয়ে ক্যালকুলাস লাগিয়ে বিস্তার করুন।

যদি না পারেন তাহলে জ্ঞান অসম্পূর্ণ। চেতনা অসম্পূর্ণ।

লেখা ছাপার জন্য নয়।

লেখার মূল উদ্দেশ্য হচ্ছে সিস্টেম 2 টা জাগিয়ে তোলা।

আমি আরো ধাপে ধাপে বুঝিয়ে বলছি 
1 বাংলা ইউনিকোড এ ডিকশনারি দরকার কেনো তার যুক্তি বুঝিয়েছি মূলত। যদি ইউনিকোড এ বাংলা ডিকশনারি প্রয়োজন এই খিদে তৈরি না হয় তাহলে এই আরটিকেল হজম হবে না স্বাভাবিক 

2 যেই জাতির প্রোগ্রাম লেখার জন্য ইউনিকোড ডিকশনারি নেই সেই জাতি বিলুপ্ত হয়ে যাবে ai এর পৃথিবীতে 
3 যেই জাতির শব্দকোষ এ শব্দের সংখ্যা বেশি সেই জাতির চিন্তা করার ক্ষমতা বেশি চেতনা ও বেশি সমৃদ্ধ 
তারপর বাংলা ভাষা বিজ্ঞান চর্চার প্রোগ্রামিং লেখার পদ্ধতি আলোচনা করেছি 
6 কোটি বাংলা valid শব্দ তৈরি করার পথ বলেছি আর 260000 টা শব্দের ইউনিকোড text ফাইল দিয়েছি লিংক গুলোতে
চেতনা সৃষ্টির জন্য চিন্তন অনুশীলন প্রয়োজন আর তার জন্য যোগ্য ভাষা প্রয়োজন।
1. চেতনা এবং সিস্টেম 2:
চেতনা (consciousness) জন্মায় গভীর, স্বতন্ত্র, বিশ্লেষণাত্মক মননের মাধ্যমে, যেটাকে Kahneman বলেন System 2।
System 1 তাড়াতাড়ি হির্বর করে টপ অফ মাইন্ড থেকে সিদ্ধান্ত নেয়, কিন্তু চেতনার বিকাশের জন্য System 2 সচেতনভাবে সক্রিয় রাখতে হয়।
চেতনা তৈরি হয় লিখে, ছবিতে আঁকে, এবং প্রতিটি ধাপ স্পষ্ট করে বিশ্লেষণ করে নির্বাক নয়, সক্রিয় প্রকাশনায়।
2. ভাষা, ইউনিকোড ও AI যুগে বাঁচার সংগ্রাম
বাংলাকে যদি ইউনিকোডভিত্তিক dictionary সহ প্রযুক্তিগতভাবে প্রমিত না করা হয়, তাহলে AI যুগে এই ভাষা পিছিয়ে পড়বে।ভাষার শব্দভাণ্ডার বড় মানেই চিন্তার ক্ষমতা বড়, কারণ চিন্তা ভাষার মাধ্যমে প্রকাশিত হয়।
৬ কোটি valid শব্দের ধারণা আসলে এক বিশাল চিন্তার ফ্রেমওয়ার্ক।
3. চেতনা এবং কোয়ান্টাম বাস্তবতা
কোয়ান্টাম ফিজিক্স আমাদের শিখিয়েছে, পর্যবেক্ষণের আগ পর্যন্ত কোনো কিছুর নির্দিষ্ট অবস্থা থাকে না।
এই পর্যবেক্ষণ কি যন্ত্র দেয়? নাকি চেতন সত্তা? Consciousness causes collapse—এই ধারণাই প্যানসাইকিজমকে যুক্তিগ্রাহ্য করে তোলে।
4. প্যানসাইকিজম
চেতনা কোনো কিছুর মধ্য দিয়ে তৈরি হয় না, বরং এটি একটি মৌলিক প্রপার্টি অর্জিত অবস্থা ও হতে পারে জেটা চার্জ বা ভরের মত।প্রত্যেক কণার হয়তো সামান্য অনুভব আছে, এবং তাদের সমন্বয়ে জটিল চেতনার গঠন সম্ভব হয়—যেমন মানুষের মস্তিষ্ক।
5. যুক্তি ও দর্শনের সংমিশ্রণ
এটি নিছক কল্পনা নয়, বরং যুক্তিসংগত একটি দর্শন যার ভিত্তি রয়েছে দর্শনে, বিজ্ঞানে, এবং গাণিতিকভাবে সাজানো চিন্তায়।
“The hard problem of consciousness” সমাধানে একমাত্র রাস্তা System 2 সক্রিয় রাখা, যুক্তির সাথে লেখা ও গাণিতিক বিশ্লেষণ চালিয়ে যাওয়া।
শিরোনাম হতেই পারে একটা বই এর
চেতনার গণিত System 2, প্যানসাইকিজম ও AI যুগে ভাষার যুদ্ধ
অধ্যায়সমূহ হতেই পারে এই চিন্তার 

1. চেতনা কি লিখে বোঝানো ছাড়া সম্ভব?
2. System 1 বনাম System 2: কোনটা তুমি?
3. ভাষা চিন্তা-চেতনা  বাংলার ভবিষ্যৎ কোথায়?
4. ইউনিকোড ও প্রোগ্রামিং ভাষার ভেতরে বাংলা
5. কোয়ান্টাম ও চেতনার মীমাংসা
6. প্যানসাইকিজম ও চেতনার মৌলিক তত্ত্ব
7. Consciousness causes collapse: দর্শন না বিজ্ঞান?
8. প্রতিটি শব্দ, প্রতিটি ধারণার গণিত ও গ্রাফ
9. নতুন মানুষ, নতুন ভাষা, নতুন বাস্তবতা
গ্রাফ থিওরি বা LPP দিয়ে চেতনার যুক্তিগুলো মডেল করতে কোয়ান্টাম ফিজিক্স ও নিউরোসায়েন্স এর সমান্তরাল দর্শন সাজিয়ে দেখতে হবে।


ভারতীয় রাগ সঙ্গীত এর জন্য প্রোগ্রামিং 

MIDI তে Key Pressure বলতে দুই ধরনের ডেটা বোঝানো হতে পারে, এবং এগুলো অনেক সময় গুলিয়ে ফেলা হয়
1. Channel Aftertouch (বা Channel Pressure)
এটি পুরো চ্যানেলের উপর ভিত্তি করে একটি মাত্র প্রেসার ভ্যালু পাঠায়।
অর্থাৎ, আপনি যদি একটি চ্যানেলে একাধিক কী বাজান, তবে এই টাইপের aftertouch সবগুলো নোটের জন্য একই প্রেসার ভ্যালু প্রয়োগ করে।
MIDI Message Format
Status byte: 0xD0 + channel
Data byte 1 প্রেসার ভ্যালু (0–127)
2. Polyphonic Aftertouch (বা Key Pressure)
এটি প্রতি কী আলাদাভাবে প্রেসার সেন্স করে — অর্থাৎ কোন কী-তে কতটা চাপ দেওয়া হচ্ছে সেটা আলাদাভাবে জানায়।
অনেক উন্নত কীবোর্ড/সিন্থে এই ফিচার থাকে।
MIDI Message Format
Status byte: 0xA0 + channel
Data byte 1 note number (0–127)
Data byte 2  প্রেসার ভ্যালু (0–127)
এর কাজ কী?
Key Pressure (Aftertouch) ব্যবহার করে নিম্নলিখিত জিনিসগুলো করা যায়
Vibrato নিয়ন্ত্রণ
Filter cutoff modulation
Volume বা expression modulation
Modulation wheel এর মত control কিন্তু finger pressure দিয়ে
উদাহরণ
 যদি কোনো কীবোর্ডে Aftertouch support করে এবং আপনি কোনো key টিপে ধরে রাখেন এবং চাপ বাড়ান, তাহলে সেই চাপ অনুযায়ী vibrato বা tone color পরিবর্তন হতে পারে।
বাস্তব ব্যবহারে
সব MIDI কীবোর্ড বা সফটওয়্যার Polyphonic Aftertouch সাপোর্ট করে না।
অনেক ডিভাইস শুধু Channel Pressure সাপোর্ট করে।
DAW গুলোতে যেমন Ableton, Logic, FL Studio  সেখানে Aftertouch automation করা যায়।
সংক্ষেপে
Key Pressure = Polyphonic Aftertouch  প্রতি কী র আলাদা চাপ বোঝায়
Channel Pressure = Channel Aftertouch  পুরো চ্যানেলের জন্য একটাই চাপ মান
 NAudio ব্যবহার করে C# এ MIDI ফাইল তৈরি করলে এবং Key Pressure (Aftertouch) বা Channel Pressure যুক্ত করতে হলে NAudio এবং MIDI তে Aftertouch ব্যবহারের মূল ধারণা 
NAudio তে MIDI বার্তা তৈরি করতে হয় MidiEvent দিয়ে। দুই ধরনের প্রেশার থাকে

1. Channel Pressure (Channel Aftertouch)

var time = 0; // tick position
var channel = 0; // MIDI Channel 1
var pressureValue = 100; // 0–127

var channelPressureEvent = new ChannelAfterTouchEvent(time, channel, pressureValue);

2. Polyphonic Aftertouch (Key Pressure)

var time = 0; // tick position
var channel = 0;
var noteNumber = 60; // Middle C
var pressureValue = 80;

var polyPressureEvent = new PolyAfterTouchEvent(time, channel, noteNumber, pressureValue);
একটি উদাহরণ যেখানে Aftertouch ব্যবহার হচ্ছে

using NAudio.Midi;

class Program
{
    static void Main()
    {
        var midiEventCollection = new MidiEventCollection(1, 480);

        int channel = 0;
        int note = 60; // Middle C
        int velocity = 100;
        int duration = 240;

        // Note On
        midiEventCollection.AddEvent(new NoteOnEvent(0, channel, note, velocity, duration), 0);

        // Polyphonic Aftertouch (Key Pressure)
        midiEventCollection.AddEvent(new PolyAfterTouchEvent(120, channel, note, 80), 0);

        // Note Off
        midiEventCollection.AddEvent(new NoteEvent(240, channel, MidiCommandCode.NoteOff, note, 0), 0);

        // End of Track
        midiEventCollection.PrepareForExport();
        MidiFile.Export("aftertouch_test.mid", midiEventCollection);
    }
}
কিছু গুরুত্বপূর্ণ বিষয়
PolyAfterTouchEvent ও ChannelAfterTouchEvent দুটোই MidiEvent থেকে তৈরি হয়।সব সফটওয়্যার বা হার্ডওয়্যার Polyphonic Aftertouch পড়তে বা রেন্ডার করতে পারে না। সেটা নির্ভর করে যে DAW বা Synth ব্যবহার করছো তার ওপর।
Export() করলে .mid ফাইল তৈরি হবে, যেটা DAW বা MIDI প্লেয়ার দিয়ে বাজানো যাবে।
 ভারতীয় শাস্ত্রীয় সঙ্গীতের MIDI রেন্ডারিংয়ের ক্ষেত্রে খুব গুরুত্বপূর্ণ। নিচে আমি ধাপে ধাপে ব্যাখ্যা করছি C# + NAudio + MIDI Pitch Bend ব্যবহার করে কীভাবে n-6 থেকে n+6 পর্যন্ত meend/murki/gamaka style glide করা যায়।
1. Pitch Bend এর রেঞ্জ (MIDI Spec)
MIDI তে Pitch Bend ভ্যালু হয় 0 থেকে 16383 (14-bit)।
8192 = center (no bend)
0 = সর্বোচ্চ নিচে (maximum pitch down)
16383 = সর্বোচ্চ উপরে (maximum pitch up)
Default pitch bend range note -/+ 6 হবে না ডিফল্ট। সেই ক্ষেত্রে সেনসিটিভিটি কম করতে হবে।RPN send করে। ডিফল্ট ±2 semitone (unless synth config is changed)
2. n - 6 থেকে n + 6 পর্যন্ত glide করতে চাইলে
কিন্তু এই ক্ষেত্রে আমরা চাই 12 semitone bend
 MIDI synth বা DAW কে জানাতে হবে যে pitch bend range ±12 semitone
কিন্তু NAudio দিয়ে .mid ফাইল বানালে daw synth configuration পাঠাতে হবে না unless
 RPN 0 (Pitch Bend Sensitivity) বার্তা দিতে হবে।
তা না হলে default daw synth ডিফল্ট 2 semitone ধরে নিচ্ছে।
3. NAudio দিয়ে Pitch Bend Event যুক্ত করার ধরন

// Pitch bend value: 14-bit (0 to 16383), 8192 is center (no bend)
int bendValue = 8192 + delta;

// delta = pitch offset in 14-bit units

// Pitch Bend Event
var pitchBendEvent = new PitchWheelChangeEvent(ticks, channel, bendValue);

// Pitch bend value: 14-bit (0 to 16383), 8192 is center (no bend)
int bendValue = 8192 + delta;

// delta = pitch offset in 14-bit units

// Pitch Bend Event
var pitchBendEvent = new PitchWheelChangeEvent(ticks, channel, bendValue);
4. 12 সেমিটোনের Mapping (assuming ±12 semitone range):
Pitch bend sensitivity ±12 হলে
প্রতি সেমিটোনে ≈ (16384 / 24) = 682.66 units
অর্থাৎ
একটার পর একটা PitchWheelChangeEvent দিয়ে Meend তৈরি করা যায়।
5. উদাহরণ (C# + NAudio) Meend Effect
using NAudio.Midi;

class Program
{
    static void Main()
    {
        var midiEvents = new MidiEventCollection(1, 480);
        int channel = 0;
        int note = 60;
        int velocity = 100;

        // Note On
        midiEvents.AddEvent(new NoteOnEvent(0, channel, note, velocity, 0), 0);

        // Pitch bend values to glide from -6 to +6 over time
        for (int i = 0; i <= 12; i++)
        {
            int semitoneOffset = i - 6;
            int bendValue = 8192 + (int)(semitoneOffset * (16384.0 / 24));
            int tick = i * 20;

            midiEvents.AddEvent(new PitchWheelChangeEvent(tick, channel, bendValue), 0);
        }

        // Note Off after meend
        midiEvents.AddEvent(new NoteEvent(300, channel, MidiCommandCode.NoteOff, note, 0), 0);

        midiEvents.PrepareForExport();
        MidiFile.Export("meend.mid", midiEvents);
    }
}
6. কীকরে “Indian meend” এর মত শোনাবে?
সব DAW বা synth pitch bend sensitivity ±2 ধরে নেয়। যদি  ±12 করতে দরকার, তাহলে .mid ফাইলের শুরুতে RPN message পাঠাতে হবে ।সব ইনস্ট্রুমেন্ট বা MIDI channel pitch bend সাপোর্ট করে না। Mono synth sounds (violin, bansuri, etc) তে এটা সবচেয়ে ভালো কাজ করে।যদি পরপর glide effect দরকার তাহলে বেশ কিছু মিলিসেকোন্ড মিডিটিক এ পর পর PitchWheelChangeEvent  টাইমিং সহ send করতে হবে।RPN এর অংশ টা বেশ কঠিন তবে আমি vlc তে fluidsynth sf2 use করে মিডি প্লে করি চালাই এবং audacity তে মিডি চালাই RPN কীকরে use করে note number n এর জন্য n -k থেকে n+r অবধি pitch bend range fit করবো সেইটা অনেক ক্যালকুলেশন এর দরকার।
সাধারণত NAudio দিয়ে .mid ফাইল তৈরি করি এবং সেটা VLC বা Audacity (যেখানে FluidSynth .sf2 ব্যবহার করে) এ প্লে করি, pitch bend range মানে ±2 semitone ডিফল্ট থাকে।
আমরা যদি Note n এর জন্য n - k থেকে n + r অবধি pitch bend ব্যবহার করতে চাই (যেমন n - 6 থেকে n + 6), তাহলে প্রথমেই .mid ফাইলের শুরুতে সেই pitch bend sensitivity সেট করতে হবে RPN মেসেজ দিয়ে।
1. তাহলে কীভাবে RPN দিয়ে Pitch Bend Sensitivity সেট করবো? কারণ শাস্ত্রীয় সঙ্গীত এর ক্ষেত্রে এটা করতেই হয়। কেবল 2 সেমিটোন  নিয়ে ভারতীয় রাগ সঙ্গীত তো হবে না।
MIDI তে Pitch Bend Sensitivity = RPN #0
RPN Message পাঠাতে হয় এইভাবে

Controller 101 (0x65) 
RPN MSB (value = 0 for pitch bend sensitivity)  
Controller 100 (0x64) 
RPN LSB (value = 0)  
Controller 6   (0x06) 
Data Entry MSB (value = number of semitones bend allowed)  
Controller 38  (0x26): Data Entry LSB (value = cents, usually 0)
2. NAudio দিয়ে কোড
 n - 6 থেকে n + 6 bend করার উপযোগী .mid ফাইল

using NAudio.Midi;

class Program
{
    static void Main()
    {
        int channel = 0;
        int baseNote = 60; // e.g., Middle C
        int velocity = 100;
        int pitchBendRange = 12; // semitone range: -6 to +6 = total 12
        int ticksPerQuarterNote = 480;

        var midiEvents = new MidiEventCollection(1, ticksPerQuarterNote);

        // 0 ticks = Start
        int absoluteTime = 0;

        // 1. Set RPN 0
//Pitch Bend Sensitivity to ±12 semitones 
        midiEvents.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.RpnMsb, 0), 0); // 101 → MSB
        midiEvents.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.RpnLsb, 0), 0); // 100 → LSB
        midiEvents.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.DataEntryMsb, pitchBendRange), 0); // 6
        midiEvents.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.DataEntryLsb, 0), 0); // 38

        // Optional: Reset RPN (to avoid accidental edits)
        midiEvents.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.RpnMsb, 127), 0);
        midiEvents.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.RpnLsb, 127), 0);

        // --- 2. Note On ---
        midiEvents.AddEvent(new NoteOnEvent(absoluteTime, channel, baseNote, velocity, 0), 0);

        // --- 3. Add Pitch Bend Meend from -6 to +6 over time ---
        for (int semitone = -6; semitone <= 6; semitone++)
        {
            int bendValue = 8192 + (int)(semitone * (8192.0 / pitchBendRange)); // linear scale
            int tick = absoluteTime + (semitone + 6) * 30; // every 30 ticks (adjust as needed)
            midiEvents.AddEvent(new PitchWheelChangeEvent(tick, channel, bendValue), 0);
        }

        // --- 4. Note Off after full bend cycle ---
        midiEvents.AddEvent(new NoteEvent(absoluteTime + 400, channel, MidiCommandCode.NoteOff, baseNote, 0), 0);

        // --- 5. Export to file ---
        midiEvents.PrepareForExport();
        MidiFile.Export("pitchbend_meend_rpn.mid", midiEvents);
    }
}

3. এই কোড কী করে?

MIDI ফাইলের শুরুতে RPN দিয়ে ±12 semitone bend sensitivity সেট করে
তারপর একটি note on করে
তারপর -6 থেকে +6 পর্যন্ত meend দেয় pitch bend দিয়ে
শেষে note off করে
4. VLC/FluidSynth এবং Audacity তে কীভাবে এটা কাজ করবে?
যদি .sf2 ফাইলের synth RPN 0 সাপোর্ট করে, তাহলে তুমি পুরো ±12 semitone bend পাবে।Audacity বা VLC যদি RPN 0 ইগনোর করে, তাহলে pitch bend range ±2 থাকবে।
এই অবস্থায় -6 semitone মানে হবে out-of-range, ফলে bend কাটা যাবে।
 .sf2 ফাইল বা FluidSynth config চেক করতে হবে pitch_bend_range সাপোর্ট করে কিনা।
5. Bonus
 n-k থেকে n+r bend কাস্টমাইজড করতে চাইলে
 k = 3, r = 5  তাহলে total = 3 + 5 = 8 semitone
তাহলে
int pitchBendRange = 8;
int bendStart = -3;
int bendEnd = +5;
bendValue হিসাব করবে এই স্কেলে
int bendValue = 8192 + (int)(semitone * (8192.0 / pitchBendRange));

 একটি Generalized C# Function চেষ্টা করা যেতে পারে যেখানে noteNumber (n), lowerBendSemitones (k), upperBendSemitones (r) ইনপুট দিয়ে .mid ফাইল বানাতে হলে যেটাতে pitch bend sensitivity k + r অনুযায়ী সেট হবে এবং note n এর চারপাশে meend (glide effect) তৈরি হবে।
Generalized C# Function (NAudio দিয়ে MIDI ফাইল)

using NAudio.Midi;
using System;

class MidiMeendGenerator
{
    public static void CreateMeendMidiFile(string outputFilePath, int noteNumber, int lowerBendSemitones, int upperBendSemitones)
    {
        int totalBendRange = lowerBendSemitones + upperBendSemitones;
        int ticksPerQuarterNote = 480;
        int channel = 0;
        int velocity = 100;
        int startTime = 0;

        var midiEvents = new MidiEventCollection(1, ticksPerQuarterNote);

        // Step 1: Set RPN 0 to configure Pitch Bend Sensitivity
        midiEvents.AddEvent(new ControlChangeEvent(startTime, channel, MidiController.RpnMsb, 0), 0);
        midiEvents.AddEvent(new ControlChangeEvent(startTime, channel, MidiController.RpnLsb, 0), 0);
        midiEvents.AddEvent(new ControlChangeEvent(startTime, channel, MidiController.DataEntryMsb, totalBendRange), 0);
        midiEvents.AddEvent(new ControlChangeEvent(startTime, channel, MidiController.DataEntryLsb, 0), 0);

        // Optional: Reset RPN
        midiEvents.AddEvent(new ControlChangeEvent(startTime, channel, MidiController.RpnMsb, 127), 0);
        midiEvents.AddEvent(new ControlChangeEvent(startTime, channel, MidiController.RpnLsb, 127), 0);

        // Step 2: Note On
        midiEvents.AddEvent(new NoteOnEvent(startTime, channel, noteNumber, velocity, 0), 0);

        // Step 3: Pitch Bend Meend from -k to +r
        int totalSteps = totalBendRange * 2; // smoother meend = more steps
        for (int i = 0; i <= totalSteps; i++)
        {
            double position = i / (double)totalSteps;
            double semitone = -lowerBendSemitones + position * totalBendRange;

            int bendValue = 8192 + (int)(semitone * (8192.0 / totalBendRange));
            int tick = startTime + i * 20; // smooth motion

            midiEvents.AddEvent(new PitchWheelChangeEvent(tick, channel, bendValue), 0);
        }

        // Step 4: Note Off after full cycle
        int endTick = startTime + (totalSteps + 10) * 20;
        midiEvents.AddEvent(new NoteEvent(endTick, channel, MidiCommandCode.NoteOff, noteNumber, 0), 0);

        // Step 5: Export
        midiEvents.PrepareForExport();
        MidiFile.Export(outputFilePath, midiEvents);
    }
}

ব্যবহার করার উদাহরণ
MidiMeendGenerator.CreateMeendMidiFile("meend_output.mid", 62, 5, 7);  
// note = D4 (62), bend from -5 to +7 semitones
VLC বা Audacity দিয়ে কিছুটা এফেক্ট তো টের পাই।
যদি FluidSynth RPN 0 সাপোর্ট করে (প্রায় সব .sf2 synth করে), তাহলে পুরো ±bend কাজ করবে।
Note 62 নিচে 5 semitone  57 পর্যন্ত (A3) bend
Note 62 উপর 7 semitone  69 পর্যন্ত (A4) bend
মোট 12 semitone bend, মানে octave level meend
Extra Features যোগ করতে হবে 
durationMilliseconds  ইনপুট নিলে কত সময় ধরে glide হবে তা কাস্টমাইজ করা যায়।Strumming effect, multiple notes, pitch curves (logarithmic, sinusoidal), velocity variation ইত্যাদি future enhancement করা যায়। note চলাকালীন তার ভেলোসিটি পরিবর্তন করা যায় না সরাসরি, কারণ MIDI NoteOn ইভেন্টে একবারই velocity সেট হয়, এবং সেটা change করা যায় না যতক্ষণ না note আবার NoteOff হয়ে যায়।ওই  "volume automation" বা "expression control" ব্যবহার করে note চলার সময় ভলিউম বাড়ানো বা কমানো করতে  হয় অবশ্যই এই কাজ MIDI Control Change (CC) message দিয়ে করা হয়।

 "Pitch bend কমলে ভলিউম বাড়বে, আর pitch bend বাড়লে ভলিউম কমবে"  এই ধরনের সম্পর্ক তৈরি করতে হলে Pitch Bend এর মানের সাথে সাথে CC#11 (Expression Controller) বা CC#7 (Main Volume) message পাঠাতে হবে।
NAudio দিয়ে কোড (Pitch Bend এর সঙ্গে Volume Automation)
int pitchBendRange = lowerSemis + upperSemis;
int totalSteps = pitchBendRange * 2;
for (int i = 0; i <= totalSteps; i++)
{
    double position = i / (double)totalSteps;
    double semitone = -lowerSemis + position * pitchBendRange;

    int bendValue = 8192 + (int)(semitone * (8192.0 / pitchBendRange));
    int tick = startTime + i * 20;

    // Pitch bend
    midiEvents.AddEvent(new PitchWheelChangeEvent(tick, channel, bendValue), 0);

    // Volume automation (inverse relation: more pitch -> less volume)
    // Value between 30 to 127 depending on bend position
    int volume = 127 - (int)(Math.Abs(semitone) / pitchBendRange * 97);
    volume = Math.Max(30, Math.Min(127, volume));

    // Send expression controller (CC #11)
    midiEvents.AddEvent(new ControlChangeEvent(tick, channel, MidiController.Expression, volume), 0);
}
ধারনা
যখন bend নিচে যাচ্ছে (negative semitone), তখন volume বাড়ছে।যখন bend উপরে যাচ্ছে (positive semitone), তখন volume কমছে।এর ফলে, শাস্ত্রীয় সঙ্গীত এর Meend এখন স্বর অনুযায়ী ভলিউমে অনুভবযোগ্য পরিবর্তন আনবে, যেটা ভারতীয় সঙ্গীতের dynamics capture করতে সাহায্য করবে।
কী ব্যবহৃত হলো এখানে?
ControlChangeEvent দিয়ে CC messages পাঠানো
CC #11 (Expression) = finer volume control (বেশিরভাগ synth এটি ভালো সাপোর্ট করে)।বিকল্প CC #7 (Main Volume) কিন্তু এটা অনেক synth এ abrupt হয়Pitch অনুযায়ী volume বাড়া/কমা sinusoidal বা logarithmic করে নিতে হবে।Velocity র মতো behave করাতে হলে expression + velocity shaping একসাথে করতে হবে। এই কোড গুলো NAudio ব্যবহার করে একটি .mid ফাইল তৈরি করে। এই ফাংশনটি নিচের কাজগুলো করে

একটি নির্দিষ্ট noteNumber চালায় অর্থাৎ স্টার্ট করে 
k সেমিটোন নিচে এবং r সেমিটোন উপরে পর্যন্ত pitch bend করে কারণ অনেক রাগ এ এটা দরকার।
pitch bend চলাকালীন volume পরিবর্তন হয় (inverse relationship) যত বেশি pitch bend, তত কম ভলিউম, যত কম bend তত বেশি ভলিউম
কোড (NAudio MIDI Generator with Meend and Dynamic Volume)

using NAudio.Midi;
using System;
using System.IO;

public class MidiMeendGenerator
{
    public static void CreateMeendMidi(int noteNumber, int k, int r, string filePath)
    {
        int channel = 0;
        int velocity = 100;
        int durationPerStep = 30; // ms per step
        int ticksPerQuarterNote = 480;

        var midiEventCollection = new MidiEventCollection(1, ticksPerQuarterNote);
        int absoluteTime = 0;

        // Note On
        midiEventCollection.AddEvent(new NoteOnEvent(absoluteTime, channel, noteNumber, velocity, 0), 0);

        // Pitch bend + expression automation
        int totalSteps = (k + r) * 2;
        for (int i = 0; i <= totalSteps; i++)
        {
            double position = i / (double)totalSteps;
            double semitone = -k + position * (k + r);
            int bendValue = 8192 + (int)(semitone * (8192.0 / (k + r)));
            bendValue = Math.Max(0, Math.Min(16383, bendValue));

            // Inverse volume logic
            int volume = 127 - (int)(Math.Abs(semitone) / (k + r) * 97);
            volume = Math.Max(30, Math.Min(127, volume));

            // Add pitch bend event
            midiEventCollection.AddEvent(new PitchWheelChangeEvent(absoluteTime, channel, bendValue), 0);

            // Add expression controller (CC 11)
            midiEventCollection.AddEvent(new ControlChangeEvent(absoluteTime, channel, MidiController.Expression, volume), 0);

            absoluteTime += durationPerStep;
        }

        // Note Off
        midiEventCollection.AddEvent(new NoteEvent(absoluteTime + 100, channel, MidiCommandCode.NoteOff, noteNumber, 0), 0);

        // End of track
        midiEventCollection.PrepareForExport();
        MidiFile.Export(filePath, midiEventCollection);

        Console.WriteLine("MIDI file saved at: " + Path.GetFullPath(filePath));
    }
}
ভারতীয় শাস্ত্রীয় সঙ্গীত এ ব্যবহার
MidiMeendGenerator.CreateMeendMidi(noteNumber: 60, k: 6, r: 6, filePath: "meend_output.mid");
এটি C note (MIDI 60) থেকে শুরু করে -6 থেকে +6 সেমিটোন পর্যন্ত মীর (meend) সহ একটি MIDI তৈরি করবে যেখানে pitchbend অনুযায়ী volume পরিবর্তন হবে।
প্রয়োজনীয় Info
VLC/FluidSynth/sf2 সাপোর্ট করে PitchWheelChangeEvent ও Expression Controller
Volume automation এখানে done via CC 11
ভারতীয় রাগ সঙ্গীত এর জন্য .mid ফাইলটি Audacity বা অন্য DAW এ টেস্ট করতে হবে। এটাকে আরো পরিমার্জিত করে sinusoidal বা logarithmic dynamic volume দিয়েও করতে হবে।




Comments

Popular posts from this blog

SANJOYNATHSMANIMMOVIES___SCENE.PY

GTTERMS_FORMALIZATION_GEOMETRIFYING_TRIGONOMETRY

actions events in itext 7