def execute(self, context):
        def evaluate(co, channel, mx):
            #co = p.co
            x, y  = co.x, 1 if co.y > self.threshold / 100 * mx else 0
            #p.co = (x, y)
            return (x, y)
        
        speaker = getSpeaker(context)
        original_action = speaker.animation_data.action
        self.new_channel_name = unique_name(speaker.channels, original_action.get("channel_name", "AA"))
        newaction = copy_sound_action(speaker, self.new_channel_name)
        ch = newaction["channel_name"]
        channels = [c for sp in context.scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]

        if newaction is None:
            return {'CANCELLED'}

        start, end = newaction.frame_range
        speaker.animation_data.action = newaction
        speaker.sound.bakeoptions.channel_name =\
                unique_name(channels, self.new_channel_name)

        rna = eval(newaction["rna"])

        fcurves = [f for f in newaction.fcurves]    
        for fcurve in fcurves:
            dp = fcurve.data_path
            channel = fcurve.data_path.strip("\"'[]")
            #print(rna[channel])
            pts = [x for  p in fcurve.sampled_points for x in evaluate(p.co, channel, rna[channel]["b"])]
            #print(pts)
            rna[channel]["a"] = 0
            rna[channel]["b"] = 1
            newaction["min"] =  rna[channel]["min"] = rna[channel]["soft_min"] = 0
            newaction["max"] =  rna[channel]["max"] = rna[channel]["soft_max"] = 1
            newaction.fcurves.remove(fcurve)
            new_fcurve = newaction.fcurves.new(dp, action_group=ch)
            new_fcurve.extrapolation = 'CONSTANT'
            new_fcurve.keyframe_points.add(len(pts) // 2)
            new_fcurve.keyframe_points.foreach_set("co", pts)
            for p in new_fcurve.keyframe_points:
                p.interpolation = 'CONSTANT'
            new_fcurve.convert_to_samples(start, end)

        newaction["rna"] = str(rna)
        speaker['_RNA_UI'].update(rna)

        if self.nla_drop:
            # need to override context to use.. cbf'd
            nla_drop(speaker, newaction, 1, self.new_channel_name)

        # testcode TODO
        self.add_to_tweaks(newaction)
        newaction.normalise = 'NONE'
        #tw.type = "COPIED FROM %s" % original_action.name
        return {'FINISHED'}
    def execute(self, context):
        def evaluate(co, channel, mx):
            #co = p.co
            x, y  = co.x, 1 if co.y > self.threshold / 100 * mx else 0
            #p.co = (x, y)
            return (x, y)
        
        speaker = getSpeaker(context)
        original_action = speaker.animation_data.action
        self.new_channel_name = unique_name(speaker.channels, original_action.get("channel_name", "AA"))
        newaction = copy_sound_action(speaker, self.new_channel_name)
        ch = newaction["channel_name"]
        channels = [c for sp in context.scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]

        if newaction is None:
            return {'CANCELLED'}

        start, end = newaction.frame_range
        speaker.animation_data.action = newaction
        speaker.sound.bakeoptions.channel_name =\
                unique_name(channels, self.new_channel_name)

        rna = eval(newaction["rna"])

        fcurves = [f for f in newaction.fcurves]    
        for fcurve in fcurves:
            dp = fcurve.data_path
            channel = fcurve.data_path.strip("\"'[]")
            #print(rna[channel])
            pts = [x for  p in fcurve.sampled_points for x in evaluate(p.co, channel, rna[channel]["b"])]
            #print(pts)
            rna[channel]["a"] = 0
            rna[channel]["b"] = 1
            newaction["min"] =  rna[channel]["min"] = rna[channel]["soft_min"] = 0
            newaction["max"] =  rna[channel]["max"] = rna[channel]["soft_max"] = 1
            newaction.fcurves.remove(fcurve)
            new_fcurve = newaction.fcurves.new(dp, action_group=ch)
            new_fcurve.extrapolation = 'CONSTANT'
            new_fcurve.keyframe_points.add(len(pts) // 2)
            new_fcurve.keyframe_points.foreach_set("co", pts)
            for p in new_fcurve.keyframe_points:
                p.interpolation = 'CONSTANT'
            new_fcurve.convert_to_samples(start, end)

        newaction["rna"] = str(rna)
        speaker['_RNA_UI'].update(rna)

        if self.nla_drop:
            # need to override context to use.. cbf'd
            nla_drop(speaker, newaction, 1, self.new_channel_name)

        # testcode TODO
        self.add_to_tweaks(newaction)
        newaction.normalise = 'NONE'
        #tw.type = "COPIED FROM %s" % original_action.name
        return {'FINISHED'}
    def copy_action(self, context):
        speaker = getSpeaker(context)
        sound = speaker.sound
        bakeoptions = sound.bakeoptions
        scene = context.scene
        layout = self.layout
        row = layout.row(align=True)
        sub = row.row()
        sub.scale_x = 2

        channels = [c for sp in scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]
        new_channel_name = unique_name(channels, bakeoptions.channel_name)
        op = sub.operator("soundaction.copy", text="Copy to Channel %s" % new_channel_name)
        op.new_channel_name = new_channel_name
        col = layout.column()
        col.operator_context = 'INVOKE_DEFAULT'
        op = col.operator("soundaction.copy_to_switches")

        '''
        row = layout.row()
        op = row.operator("sound.bake_animation")
        row = layout.column()
        row.prop(scene, "sync_mode", expand=True)
        '''
        return
    def copy_action(self, context):
        speaker = getSpeaker(context)
        sound = speaker.sound
        bakeoptions = sound.bakeoptions
        scene = context.scene
        layout = self.layout
        row = layout.row(align=True)
        sub = row.row()
        sub.scale_x = 2

        channels = [c for sp in scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]
        new_channel_name = unique_name(channels, bakeoptions.channel_name)
        op = sub.operator("soundaction.copy", text="Copy to Channel %s" % new_channel_name)
        op.new_channel_name = new_channel_name
        col = layout.column()
        col.operator_context = 'INVOKE_DEFAULT'
        op = col.operator("soundaction.copy_to_switches")

        '''
        row = layout.row()
        op = row.operator("sound.bake_animation")
        row = layout.column()
        row.prop(scene, "sync_mode", expand=True)
        '''
        return
    def execute(self, context):
        speaker = getSpeaker(context)
        original_action = speaker.animation_data.action
        newaction = copy_sound_action(speaker, self.new_channel_name)
        channels = [c for sp in context.scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]

        if newaction is not None:
            speaker.animation_data.action = newaction
            speaker.sound.bakeoptions.channel_name =\
                    unique_name(channels, "AA")
                    #unique_name(channels, self.new_channel_name)

            if self.nla_drop:
                # need to override context to use.. cbf'd
                nla_drop(speaker, newaction, 1, self.new_channel_name)

            self.add_to_tweaks(newaction)
            #tw.type = "COPIED FROM %s" % original_action.name
            return {'FINISHED'}

        return {'CANCELLED'}
    def execute(self, context):
        speaker = getSpeaker(context)
        original_action = speaker.animation_data.action
        newaction = copy_sound_action(speaker, self.new_channel_name)
        channels = [c for sp in context.scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]

        if newaction is not None:
            speaker.animation_data.action = newaction
            speaker.sound.bakeoptions.channel_name =\
                    unique_name(channels, "AA")
                    #unique_name(channels, self.new_channel_name)

            if self.nla_drop:
                # need to override context to use.. cbf'd
                nla_drop(speaker, newaction, 1, self.new_channel_name)

            self.add_to_tweaks(newaction)
            #tw.type = "COPIED FROM %s" % original_action.name
            return {'FINISHED'}

        return {'CANCELLED'}
Exemple #7
0
def read_midi_file(context, filepath, use_some_setting):
    print(filepath)
    prefs = context.user_preferences.addons["sound_drivers"].preferences
    import sys

    sys.path.append(prefs.smf_dir)
    import smf

    pin_id = context.space_data.pin_id
    sp = pin_id if pin_id is not None else context.object.data

    channels = [c for sp in context.scene.objects if sp.type == "SPEAKER" for c in sp.data.channels]
    midichannels = []
    f = smf.SMF(filepath)
    tracks = []
    for t in f.tracks:
        print("TRACK : %s" % t.track_number)
        a = {}
        # a = bpy.data.actions.new("MidiAction")

        print(channels)
        channel_name = unique_name(channels, "AA")
        channels.append(channel_name)
        a["name"] = "%s Unknown (trk %d)" % (channel_name, t.track_number)
        a["wavfile"] = sp.sound.name
        a["start"] = 0
        a["end"] = len(midi_notes)
        a["row_height"] = 0.4
        a["Channels"] = 0
        a["channel_name"] = channel_name
        a["MIDI"] = filepath
        # sp.animation_data.action = a
        a["keyframe_points"] = {}  # list of tups (dp, frame, value)

        """
        for i, n in enumerate(midi_notes):
            channel = "%s%d" % (channel_name, i)
            sp[channel] = 0
            sp.keyframe_insert('["%s"]' % channel, frame = 0)
            #sp.keyframe_insert('["%s"]' % channel, frame = 0)
            #sp.keyframe_insert('["%s"]' % channel, frame = 0)
        """
        for e in t.events:
            s = e.decode()
            print("XXXXXXXX", s, e.time_seconds)
            # print(s.startswith("Note"))

            if s.startswith("Instrument"):
                print("INSTRUMENT", s)
                a["name"] = "%s:%s (trk %d)" % (channel_name, s.title(), t.track_number)
            elif s.startswith("Key Signature"):
                print("KEYSIG", s)
            elif s.startswith("Program Change"):
                # print("PROGCHA", s)
                # this could be instrument too
                idx = int(s.split(" ")[-1])
                # print(midi_instruments[idx])
                a["name"] = "%s:%s (trk %d)" % (channel_name, midi_instruments[idx].title(), t.track_number)
            elif s.startswith("Controller"):
                continue
                print("CONTROLLER", s)
            elif s.startswith("Pitch Wheel"):
                print("PITCHWEEL", s)
                # do nothing for now
                continue
            elif s.startswith("Note"):
                v = 0
                s = s.replace("Note ", "")
                # print("StartsWithNote", s)
                c = s.split(",")
                # print("CC", c[0])
                v = int(c[3].replace(" velocity ", ""))
                if c[0] == "On":
                    note = c[2].replace(" note ", "")
                    print("ON key[%s] = %d @ %fs" % (note, v, e.time_seconds))
                elif c[0] == "Off":
                    v = 0
                    note = c[2].replace(" note ", "")
                    print("OFF key[%s] = %d @ %fs" % (note, v, e.time_seconds))
                if note not in midi_notes:
                    print("WARNING: unable to use note %s %d" % notesplit(note))
                    continue
                channel = "%s%i" % (channel_name, midi_notes.index(note))
                fcurve = a["keyframe_points"].setdefault(channel, [])
                fcurve.append((e.time_seconds * context.scene.render.fps, v))
                # sp[channel] = v
                # a["keyframe_points"].append(('["%s"]' % channel, e.time_seconds * context.scene.render.fps, v))
            else:
                # continue
                print("XXX", s)

        if len(a["keyframe_points"].keys()):
            midichannels.append(channel_name)
            midifile["TRACK : %s" % t.track_number] = a

    print(midichannels)

    keys = ["name", "wavfile", "start", "end", "row_height", "Channels", "channel_name", "MIDI"]
    actions = []
    channels = []
    action = bpy.data.actions.new("MidiAction")
    sp.animation_data.action = action
    for k, a in midifile.items():
        print("-" * 77)
        print(midifile[k]["name"])

        tracks = a["keyframe_points"]

        # action = bpy.data.actions.new("MidiAction")
        # sp.animation_data.action = action
        for key in keys:
            action[key] = a[key]
        channel = a["channel_name"]
        channels.append(channel)
        for t in tracks.keys():
            kfps = tracks[t]
            print(t)
            # fc = action.fcurves.new('["%s"]' % t)
            # make the fcurves
            sp[t] = 0
            sp.keyframe_insert('["%s"]' % t, frame=1, group=a["name"])
            for kfp in kfps:
                f, v = kfp
                sp[t] = v
                sp.keyframe_insert('["%s"]' % t, frame=f, group=a["name"])
            print("KFPS", t, len(tracks[t]))

    actions.append(action)

    # would normally load the data here

    vals = []
    sp_rna = {}
    for a in actions:

        if len(a.fcurves) <= 1:
            print("NO FCURVES IN ", a.name)
            try:
                del (a["wavfile"])
                a.user_clear()
                actions.remove(a)
                # bpy.data.actions.remove(a)
                # print("REMOVED")
            except:
                print("XCPT")
                continue
            print("WTF")
            continue

        a["Channels"] = len(a.fcurves)
        a["channels"] = channels
        channel_name = a["channel_name"]

        for fc in a.fcurves:

            for kp in fc.keyframe_points:
                kp.interpolation = "CONSTANT"
            fc_range, points = fc.minmax
            cn = fc.data_path.replace('["', "").replace('"]', "")
            print(channel_name, cn)
            n = int(cn[2:])
            f = pow(2, (n - 69) / 12.0) * 440
            high = low = f
            vals.extend(list(fc_range))
            rna = sp["_RNA_UI"]
            set_channel_idprop_rna(cn, rna, low, high, fc_range, fc_range, is_music=True)

            """
            vcns = ["%s%d" % (channel_name, i) for i in
                    range(len(midi_notes))]

            """
        sp_rna = {k: sp["_RNA_UI"][k].to_dict() for k in sp["_RNA_UI"].keys()}
        # if k in vcns}

        a["rna"] = str(sp_rna)
        a["min"] = min(vals)
        a["max"] = max(vals)

        nla_drop(sp, action, 1, "%s %s" % (channel_name, channel_name))

    return {"FINISHED"}
    def execute(self, context):
        
        BakeSoundPanel.bake_times = []
        wm = context.window_manager
        wm_rnaui = wm.get("_RNA_UI")
        if wm_rnaui is None:
            wm_rnaui = wm["_RNA_UI"] = {}
            wm["_RNA_UI"]["bake_progress"] = {
                                              "min": 0.0,
                                              "soft_min":0.0,
                                              "hard_min":0.0,
                                              "soft_max":100.0,
                                              "hard_max":100.0,
                                              "max":100.0,
                                              "description": "Baking....",
                                              }
        wm["bake_progress"] = 0.0
        BakeSoundPanel.cancel_baking = False
        self.speaker = bpy.data.speakers.get(self.speaker_name)
        self.c = context.copy()
        self.first_baked = False
        self.last_baked = False
        self.sound = bpy.data.sounds.get(self.sound_name)
        if not (self.sound and self.speaker):
            return {'CANCELLED'}
        bakeoptions = self.sound.bakeoptions
        channels = [c for sp in context.scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]
        bakeoptions.channel_name = utils.unique_name(channels, "AA") # AAAA
        self.retries = []

        if self.area_index > -1:
            '''
            self.view3d = get_context_area(context, {}, 'VIEW_3D',
                                  context_screen=True)
            '''
            self.view3d = context.screen.areas[self.area_index]
            self._view3d = self.view3d.type
            if self.view3d is not None:
                self.view3d.type = 'GRAPH_EDITOR'

        # NEEDS REFACTO to get BGL Graph Area if there is one
        self.graph = utils.get_context_area(context,
                              self.c,
                              'GRAPH_EDITOR',
                              context_screen=(self.area_index != -1))

        self.context_override = self.graph is not None\
                and self.graph.spaces.active.mode != 'DRIVERS'

        if "_RNA_UI" not in self.speaker.keys():
            self.speaker["_RNA_UI"] = dict()

        context.scene.frame_set(1)
        channels = bakeoptions.channels

        # Create the action # might move this to see if one channel baked
        current_action = None
        if not self.speaker.animation_data:
            self.speaker.animation_data_create()
        elif self.speaker.animation_data.action:
            current_action = self.speaker.animation_data.action

        name = "%s_%s_%s" % (bakeoptions.sound_type, bakeoptions.channel_name, self.sound.name)

        action = bpy.data.actions.new(name)

        if current_action:
            #take some settings from last baked
            action.vismode = current_action.vismode

        action["Channels"] = channels
        action["channel_name"] = bakeoptions.channel_name
        action["minf"] = bakeoptions.minf
        action["maxf"] = bakeoptions.maxf
        action["use_log"] = bakeoptions.use_log
        action["wavfile"] = self.sound.name
        action["min"] = 1000000
        action["max"] = -1000000
        action["start"] = 0
        action["end"] = channels - 1

        #keep some UI stuff here too like the row height of each channel

        # use 0.4 as a default value
        action["row_height"] = 0.4
        action_rna = {}
        action_rna["row_height"] = {"min": 0.001,
                                    "max": 1.0,
                                    "description": "Alter the row height",
                                    "soft_min": 0.0,
                                    "soft_max": 1.0}
        action_rna["start"] = {"min": 0,
                               "max": 1.0,
                               "description": "Clip Start",
                               "soft_min": 0,
                               "soft_max": channels - 1}
        action_rna["end"] = {"min": 1,
                             "max": channels - 1,
                             "description": "Clip End",
                             "soft_min": 1,
                             "soft_max": channels - 1}

        action["_RNA_UI"] = action_rna
        #action["rna"] = str(action_rna)
        # set up the fcurves
        BakeSoundPanel.action = action
        BakeSoundPanel.wait = 0
        BakeSoundPanel.status = [0 for i in range(channels)]
        for i in range(channels):
            p = "%s%d" % (bakeoptions.channel_name, i)
            self.speaker[p] = 0.0
            fc = action.fcurves.new('["%s"]' % p, action_group=bakeoptions.channel_name)
            fc.select = False
            fc.mute = True

        bakeorder = [i for i in range(channels)]
        if channels > 1:
            bakeorder[1], bakeorder[channels - 1] = bakeorder[channels - 1],\
                                                    bakeorder[1]
        self.bakeorder = bakeorder

        self.speaker.animation_data.action = action
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.1, context.window)
        context.window_manager.modal_handler_add(self)
        self.wait = 30
        print("-" * 80)
        print("BAKING %s to action %s" % (self.sound.name, action.name))
        print("-" * 80)

        return {'RUNNING_MODAL'}
    def draw(self, context):
        space = context.space_data
        layout = self.layout

        if self.baking:
            action = self.action
            #self.draw_progress_slider(context)

            row = layout.row()
            row.label("[%s] %s" % (action["channel_name"], action.name), icon='ACTION')
            self.draw_progress_slider(context)
            '''
            if channels > 24:
                i = getattr(self, "channel", 0)
                self.draw_current_fcurve_slider(context, i=i)
            else:
                self.draw_fcurve_slider(context)
            '''
            box = layout.box()
            if len(action.fcurves):
                row = box.row(align=False)
                i = getattr(self, "channel", 0)
                fc = action.fcurves[i]
                sub = row.row()
                sub.alignment = 'LEFT'
                sub.label(fc.data_path.strip('["]'))
                color = [c for c in fc.color]
                color.append(1.0)
                row.label("Baking...")
                sub = row.row()
                sub.alignment = 'RIGHT'
                sub.template_node_socket(color=color)

            box = layout.box()

            if len(self.bake_times):
                row = box.row(align=False)
                i = getattr(self, "channel", 0)
                fc = action.fcurves[i]
                sub = row.row()
                sub.alignment = 'LEFT'
                sub.label(fc.data_path.strip('["]'))
                color = [c for c in fc.color]
                color.append(1.0)
                row.label("Baked")
                sub = row.row()
                sub.alignment = 'RIGHT'
                sub.template_node_socket(color=color)
                row = box.row(align=False)
                row.label(BakeSoundPanel.report)
                row = box.row()
                row.label("Baked in: %02d:%02d.%02d" % utils.splittime(self.bake_times[-1]))
                row = box.row()
                te = sum(self.bake_times)
                abt = te / len(self.bake_times)
                channels = self.action.get("Channels", 0)
                tr = (channels - len(self.bake_times)) * abt

                row.label("Elapsed: %02d:%02d.%02d" % utils.splittime(te))
                row.label("Remaining: %02d:%02d.%02d" % utils.splittime(tr))
            #row.column_flow(columns=10, align=True)

            return None


        speaker = utils.getSpeaker(context)
        sound = speaker.sound

        if sound is None:
            row = layout.row()
            row.label("No Sound to Bake", icon='INFO')
            return None

        scene = context.scene

        bakeoptions = sound.bakeoptions
        bake_operator = bakeoptions.bake_operator

        # Settings for bake sound to fcurve Operator
        if not self.baking:
            areas = [a.type for a in context.screen.areas]
            if 'GRAPH_EDITOR' in areas:
                area_index = areas.index('GRAPH_EDITOR')
                op = layout.operator("wm.bake_sound_to_action", text="BAKE",
                                icon='FCURVE')
                op.area_index = area_index
                op.sound_name = sound.name
                op.speaker_name = speaker.name
    
            elif len(areas) > 1:
                self.draw_area_buttons(context)
            else:
                op = layout.operator("wm.bake_sound_to_action", text="BAKE",
                                icon='FCURVE')
    
                op.sound_name = sound.name
                op.speaker_name = speaker.name

        ### TEST FOR SQUIZ
        action = None
        channels = 0
        if speaker.animation_data:
            action = speaker.animation_data.action
            if action is not None:
                channels = action["Channels"]


        #row.operator(self.bl_idname).preset = "FOOBAR"
        row = layout.row()
        
        col = layout.column_flow(align=True)
        col.label("Bake Options")
        row = col.row(align=True)
        row.menu("speaker.preset_menu",
                 text=getattr(bpy.types, "speaker.preset_menu").bl_label)
        row.operator("wm.soundtool_operator_preset_add", text="", icon='ZOOMIN')
        row.operator("wm.soundtool_operator_preset_add", text="", icon='ZOOMOUT').remove_active = True
        
        
        #row.prop(bakeoptions, "show_graph_editor", toggle=True, emboss=True)
        '''
        preset_box = row.box()
        row = preset_box.row()
        if len(bakeoptions.preset) == 0:
            txt = "Select Preset"
        else:
            txt = bakeoptions.preset
        row.menu("speaker.preset_menu", text=txt)
        row = preset_box.row()
        #row.prop(bakeoptions, "save_preset")
        preset_row = preset_box.row()
        preset_row.prop(bakeoptions, "preset")
        row = layout.row()
        row.menu("sound.music_notes")
        '''
        channels = [c for sp in context.scene.objects if sp.type == 'SPEAKER' for c in sp.data.channels]
        channel_name = utils.unique_name(channels, "AA")
        row = layout.row()
        row.label("%s_%s_%s" % (bakeoptions.sound_type, channel_name, sound.name), icon='ACTION')
        abox = layout.box()
        arow = abox.row(align=True)
        arow.prop(bakeoptions, "sound_type", text="")

        arow.label(channel_name)
        #arow.prop(bakeoptions, "channel_name", text="")
        arow.label(sound.name)
        #arow.prop(bakeoptions, "action_name", text="") # REFACTO OUT

        row = layout.row()
        '''
        if not validate_channel_name(context):
            row.label("Channel in USE or INVALID", icon='ERROR')
            row.alert = True
            row = layout.row()

        '''
        #col.scale_x = row.scale_y = 2

        row.label("Channel")
        row = layout.row()
        box = row.box()
        #col.scale_x = row.scale_y = 2
        brow = box.row(align=True)
        #brow.prop(bakeoptions, "channel_name", text="Name")
        sub = brow.row()
        sub.prop(bakeoptions, "channels", text="")
        sub.enabled = bakeoptions.sound_type != 'MUSIC'
        row = layout.row()

        self.draw_freqs(layout, bakeoptions)
        row = layout.row()

        row.label("Bake Sound to F-Curves", icon='IPO')
        box = layout.box()
        #box.operator("graph.sound_bake", icon='IPO')
        box.prop(bake_operator, "threshold")
        box.prop(bake_operator, "release")
        box.prop(bake_operator, 'attack')
        box.prop(bake_operator, "use_additive", icon="PLUS")
        box.prop(bake_operator, "use_accumulate", icon="PLUS")

        row = box.row()

        split = row.split(percentage=0.20)
        split.prop(bake_operator, "use_square")
        split.prop(bake_operator, "sthreshold")
Exemple #10
0
def read_midi_file(context, filepath, use_some_setting):
    print(filepath)
    prefs = context.user_preferences.addons["sound_drivers"].preferences
    import sys
    sys.path.append(prefs.smf_dir)
    import smf
    pin_id = context.space_data.pin_id
    sp = pin_id if pin_id is not None else context.object.data

    channels = [
        c for sp in context.scene.objects if sp.type == 'SPEAKER'
        for c in sp.data.channels
    ]
    midichannels = []
    f = smf.SMF(filepath)
    tracks = []
    for t in f.tracks:
        print("TRACK : %s" % t.track_number)
        a = {}
        #a = bpy.data.actions.new("MidiAction")

        print(channels)
        channel_name = unique_name(channels, 'AA')
        channels.append(channel_name)
        a["name"] = "%s Unknown (trk %d)" % (channel_name, t.track_number)
        a['wavfile'] = sp.sound.name
        a['start'] = 0
        a['end'] = len(midi_notes)
        a['row_height'] = 0.4
        a["Channels"] = 0
        a["channel_name"] = channel_name
        a['MIDI'] = filepath
        #sp.animation_data.action = a
        a["keyframe_points"] = {}  # list of tups (dp, frame, value)
        '''
        for i, n in enumerate(midi_notes):
            channel = "%s%d" % (channel_name, i)
            sp[channel] = 0
            sp.keyframe_insert('["%s"]' % channel, frame = 0)
            #sp.keyframe_insert('["%s"]' % channel, frame = 0)
            #sp.keyframe_insert('["%s"]' % channel, frame = 0)
        '''
        for e in t.events:
            s = e.decode()
            print("XXXXXXXX", s, e.time_seconds)
            #print(s.startswith("Note"))

            if s.startswith("Instrument"):
                print("INSTRUMENT", s)
                a["name"] = "%s:%s (trk %d)" % (channel_name, s.title(),
                                                t.track_number)
            elif s.startswith("Key Signature"):
                print("KEYSIG", s)
            elif s.startswith("Program Change"):
                #print("PROGCHA", s)
                # this could be instrument too
                idx = int(s.split(" ")[-1])
                #print(midi_instruments[idx])
                a["name"] = "%s:%s (trk %d)" % (channel_name,
                                                midi_instruments[idx].title(),
                                                t.track_number)
            elif s.startswith("Controller"):
                continue
                print("CONTROLLER", s)
            elif s.startswith("Pitch Wheel"):
                print("PITCHWEEL", s)
                # do nothing for now
                continue
            elif s.startswith("Note"):
                v = 0
                s = s.replace("Note ", "")
                #print("StartsWithNote", s)
                c = s.split(",")
                #print("CC", c[0])
                v = int(c[3].replace(" velocity ", ""))
                if c[0] == "On":
                    note = c[2].replace(" note ", "")
                    print("ON key[%s] = %d @ %fs" % (note, v, e.time_seconds))
                elif c[0] == "Off":
                    v = 0
                    note = c[2].replace(" note ", "")
                    print("OFF key[%s] = %d @ %fs" % (note, v, e.time_seconds))
                if note not in midi_notes:
                    print("WARNING: unable to use note %s %d" %
                          notesplit(note))
                    continue
                channel = "%s%i" % (channel_name, midi_notes.index(note))
                fcurve = a["keyframe_points"].setdefault(channel, [])
                fcurve.append((e.time_seconds * context.scene.render.fps, v))
                #sp[channel] = v
                #a["keyframe_points"].append(('["%s"]' % channel, e.time_seconds * context.scene.render.fps, v))
            else:
                #continue
                print("XXX", s)

        if len(a["keyframe_points"].keys()):
            midichannels.append(channel_name)
            midifile["TRACK : %s" % t.track_number] = a

    print(midichannels)

    keys = [
        "name", "wavfile", "start", "end", "row_height", "Channels",
        "channel_name", "MIDI"
    ]
    actions = []
    channels = []
    action = bpy.data.actions.new("MidiAction")
    sp.animation_data.action = action
    for k, a in midifile.items():
        print("-" * 77)
        print(midifile[k]["name"])

        tracks = a["keyframe_points"]

        #action = bpy.data.actions.new("MidiAction")
        #sp.animation_data.action = action
        for key in keys:
            action[key] = a[key]
        channel = a["channel_name"]
        channels.append(channel)
        for t in tracks.keys():
            kfps = tracks[t]
            print(t)
            #fc = action.fcurves.new('["%s"]' % t)
            # make the fcurves
            sp[t] = 0
            sp.keyframe_insert('["%s"]' % t, frame=1, group=a["name"])
            for kfp in kfps:
                f, v = kfp
                sp[t] = v
                sp.keyframe_insert('["%s"]' % t, frame=f, group=a["name"])
            print("KFPS", t, len(tracks[t]))

    actions.append(action)

    # would normally load the data here

    vals = []
    sp_rna = {}
    for a in actions:

        if len(a.fcurves) <= 1:
            print("NO FCURVES IN ", a.name)
            try:
                del (a["wavfile"])
                a.user_clear()
                actions.remove(a)
                #bpy.data.actions.remove(a)
                #print("REMOVED")
            except:
                print("XCPT")
                continue
            print("WTF")
            continue

        a["Channels"] = len(a.fcurves)
        a["channels"] = channels
        channel_name = a["channel_name"]

        for fc in a.fcurves:

            for kp in fc.keyframe_points:
                kp.interpolation = 'CONSTANT'
            fc_range, points = fc.minmax
            cn = fc.data_path.replace('["', '').replace('"]', '')
            print(channel_name, cn)
            n = int(cn[2:])
            f = pow(2, (n - 69) / 12.0) * 440
            high = low = f
            vals.extend(list(fc_range))
            rna = sp['_RNA_UI']
            set_channel_idprop_rna(cn,
                                   rna,
                                   low,
                                   high,
                                   fc_range,
                                   fc_range,
                                   is_music=True)
            '''
            vcns = ["%s%d" % (channel_name, i) for i in
                    range(len(midi_notes))]

            '''
        sp_rna = {k: sp['_RNA_UI'][k].to_dict() for k in sp['_RNA_UI'].keys()}
        # if k in vcns}

        a['rna'] = str(sp_rna)
        a['min'] = min(vals)
        a['max'] = max(vals)

        nla_drop(sp, action, 1, "%s %s" % (channel_name, channel_name))

    return {'FINISHED'}
Exemple #11
0
    def execute(self, context):

        BakeSoundPanel.bake_times = []
        wm = context.window_manager
        wm_rnaui = wm.get("_RNA_UI")
        if wm_rnaui is None:
            wm_rnaui = wm["_RNA_UI"] = {}
            wm["_RNA_UI"]["bake_progress"] = {
                "min": 0.0,
                "soft_min": 0.0,
                "hard_min": 0.0,
                "soft_max": 100.0,
                "hard_max": 100.0,
                "max": 100.0,
                "description": "Baking....",
            }
        wm["bake_progress"] = 0.0
        BakeSoundPanel.cancel_baking = False
        self.speaker = bpy.data.speakers.get(self.speaker_name)
        self.c = context.copy()
        self.first_baked = False
        self.last_baked = False
        self.sound = bpy.data.sounds.get(self.sound_name)
        if not (self.sound and self.speaker):
            return {'CANCELLED'}
        bakeoptions = self.sound.bakeoptions
        channels = [
            c for sp in context.scene.objects if sp.type == 'SPEAKER'
            for c in sp.data.channels
        ]
        bakeoptions.channel_name = utils.unique_name(channels, "AA")  # AAAA
        self.retries = []

        if self.area_index > -1:
            '''
            self.view3d = get_context_area(context, {}, 'VIEW_3D',
                                  context_screen=True)
            '''
            self.view3d = context.screen.areas[self.area_index]
            self._view3d = self.view3d.type
            if self.view3d is not None:
                self.view3d.type = 'GRAPH_EDITOR'

        # NEEDS REFACTO to get BGL Graph Area if there is one
        self.graph = utils.get_context_area(
            context,
            self.c,
            'GRAPH_EDITOR',
            context_screen=(self.area_index != -1))

        self.context_override = self.graph is not None\
                and self.graph.spaces.active.mode != 'DRIVERS'

        if "_RNA_UI" not in self.speaker.keys():
            self.speaker["_RNA_UI"] = dict()

        context.scene.frame_set(1)
        channels = bakeoptions.channels

        # Create the action # might move this to see if one channel baked
        current_action = None
        if not self.speaker.animation_data:
            self.speaker.animation_data_create()
        elif self.speaker.animation_data.action:
            current_action = self.speaker.animation_data.action

        name = "%s_%s_%s" % (bakeoptions.sound_type, bakeoptions.channel_name,
                             self.sound.name)

        action = bpy.data.actions.new(name)

        if current_action:
            #take some settings from last baked
            action.vismode = current_action.vismode

        action["Channels"] = channels
        action["channel_name"] = bakeoptions.channel_name
        action["minf"] = bakeoptions.minf
        action["maxf"] = bakeoptions.maxf
        action["use_log"] = bakeoptions.use_log
        action["wavfile"] = self.sound.name
        action["min"] = 1000000
        action["max"] = -1000000
        action["start"] = 0
        action["end"] = channels - 1

        #keep some UI stuff here too like the row height of each channel

        # use 0.4 as a default value
        action["row_height"] = 0.4
        action_rna = {}
        action_rna["row_height"] = {
            "min": 0.001,
            "max": 1.0,
            "description": "Alter the row height",
            "soft_min": 0.0,
            "soft_max": 1.0
        }
        action_rna["start"] = {
            "min": 0,
            "max": 1.0,
            "description": "Clip Start",
            "soft_min": 0,
            "soft_max": channels - 1
        }
        action_rna["end"] = {
            "min": 1,
            "max": channels - 1,
            "description": "Clip End",
            "soft_min": 1,
            "soft_max": channels - 1
        }

        action["_RNA_UI"] = action_rna
        #action["rna"] = str(action_rna)
        # set up the fcurves
        BakeSoundPanel.action = action
        BakeSoundPanel.wait = 0
        BakeSoundPanel.status = [0 for i in range(channels)]
        for i in range(channels):
            p = "%s%d" % (bakeoptions.channel_name, i)
            self.speaker[p] = 0.0
            fc = action.fcurves.new('["%s"]' % p,
                                    action_group=bakeoptions.channel_name)
            fc.select = False
            fc.mute = True

        bakeorder = [i for i in range(channels)]
        if channels > 1:
            bakeorder[1], bakeorder[channels - 1] = bakeorder[channels - 1],\
                                                    bakeorder[1]
        self.bakeorder = bakeorder

        self.speaker.animation_data.action = action
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.1, context.window)
        context.window_manager.modal_handler_add(self)
        self.wait = 30
        print("-" * 80)
        print("BAKING %s to action %s" % (self.sound.name, action.name))
        print("-" * 80)

        return {'RUNNING_MODAL'}
Exemple #12
0
    def draw(self, context):
        space = context.space_data
        layout = self.layout

        if self.baking:
            action = self.action
            #self.draw_progress_slider(context)

            row = layout.row()
            row.label("[%s] %s" % (action["channel_name"], action.name),
                      icon='ACTION')
            self.draw_progress_slider(context)
            '''
            if channels > 24:
                i = getattr(self, "channel", 0)
                self.draw_current_fcurve_slider(context, i=i)
            else:
                self.draw_fcurve_slider(context)
            '''
            box = layout.box()
            if len(action.fcurves):
                row = box.row(align=False)
                i = getattr(self, "channel", 0)
                fc = action.fcurves[i]
                sub = row.row()
                sub.alignment = 'LEFT'
                sub.label(fc.data_path.strip('["]'))
                color = [c for c in fc.color]
                color.append(1.0)
                row.label("Baking...")
                sub = row.row()
                sub.alignment = 'RIGHT'
                sub.template_node_socket(color=color)

            box = layout.box()

            if len(self.bake_times):
                row = box.row(align=False)
                i = getattr(self, "channel", 0)
                fc = action.fcurves[i]
                sub = row.row()
                sub.alignment = 'LEFT'
                sub.label(fc.data_path.strip('["]'))
                color = [c for c in fc.color]
                color.append(1.0)
                row.label("Baked")
                sub = row.row()
                sub.alignment = 'RIGHT'
                sub.template_node_socket(color=color)
                row = box.row(align=False)
                row.label(BakeSoundPanel.report)
                row = box.row()
                row.label("Baked in: %02d:%02d.%02d" %
                          utils.splittime(self.bake_times[-1]))
                row = box.row()
                te = sum(self.bake_times)
                abt = te / len(self.bake_times)
                channels = self.action.get("Channels", 0)
                tr = (channels - len(self.bake_times)) * abt

                row.label("Elapsed: %02d:%02d.%02d" % utils.splittime(te))
                row.label("Remaining: %02d:%02d.%02d" % utils.splittime(tr))
            #row.column_flow(columns=10, align=True)

            return None

        speaker = utils.getSpeaker(context)
        sound = speaker.sound

        if sound is None:
            row = layout.row()
            row.label("No Sound to Bake", icon='INFO')
            return None

        scene = context.scene

        bakeoptions = sound.bakeoptions
        bake_operator = bakeoptions.bake_operator

        # Settings for bake sound to fcurve Operator
        if not self.baking:
            areas = [a.type for a in context.screen.areas]
            if 'GRAPH_EDITOR' in areas:
                area_index = areas.index('GRAPH_EDITOR')
                op = layout.operator("wm.bake_sound_to_action",
                                     text="BAKE",
                                     icon='FCURVE')
                op.area_index = area_index
                op.sound_name = sound.name
                op.speaker_name = speaker.name

            elif len(areas) > 1:
                self.draw_area_buttons(context)
            else:
                op = layout.operator("wm.bake_sound_to_action",
                                     text="BAKE",
                                     icon='FCURVE')

                op.sound_name = sound.name
                op.speaker_name = speaker.name

        ### TEST FOR SQUIZ
        action = None
        channels = 0
        if speaker.animation_data:
            action = speaker.animation_data.action
            if action is not None:
                channels = action["Channels"]

        #row.operator(self.bl_idname).preset = "FOOBAR"
        row = layout.row()

        col = layout.column_flow(align=True)
        col.label("Bake Options")
        row = col.row(align=True)
        row.menu("speaker.preset_menu",
                 text=getattr(bpy.types, "speaker.preset_menu").bl_label)
        row.operator("wm.soundtool_operator_preset_add",
                     text="",
                     icon='ZOOMIN')
        row.operator("wm.soundtool_operator_preset_add",
                     text="",
                     icon='ZOOMOUT').remove_active = True

        #row.prop(bakeoptions, "show_graph_editor", toggle=True, emboss=True)
        '''
        preset_box = row.box()
        row = preset_box.row()
        if len(bakeoptions.preset) == 0:
            txt = "Select Preset"
        else:
            txt = bakeoptions.preset
        row.menu("speaker.preset_menu", text=txt)
        row = preset_box.row()
        #row.prop(bakeoptions, "save_preset")
        preset_row = preset_box.row()
        preset_row.prop(bakeoptions, "preset")
        row = layout.row()
        row.menu("sound.music_notes")
        '''
        channels = [
            c for sp in context.scene.objects if sp.type == 'SPEAKER'
            for c in sp.data.channels
        ]
        channel_name = utils.unique_name(channels, "AA")
        row = layout.row()
        row.label("%s_%s_%s" %
                  (bakeoptions.sound_type, channel_name, sound.name),
                  icon='ACTION')
        abox = layout.box()
        arow = abox.row(align=True)
        arow.prop(bakeoptions, "sound_type", text="")

        arow.label(channel_name)
        #arow.prop(bakeoptions, "channel_name", text="")
        arow.label(sound.name)
        #arow.prop(bakeoptions, "action_name", text="") # REFACTO OUT

        row = layout.row()
        '''
        if not validate_channel_name(context):
            row.label("Channel in USE or INVALID", icon='ERROR')
            row.alert = True
            row = layout.row()

        '''
        #col.scale_x = row.scale_y = 2

        row.label("Channel")
        row = layout.row()
        box = row.box()
        #col.scale_x = row.scale_y = 2
        brow = box.row(align=True)
        #brow.prop(bakeoptions, "channel_name", text="Name")
        sub = brow.row()
        sub.prop(bakeoptions, "channels", text="")
        sub.enabled = bakeoptions.sound_type != 'MUSIC'
        row = layout.row()

        self.draw_freqs(layout, bakeoptions)
        row = layout.row()

        row.label("Bake Sound to F-Curves", icon='IPO')
        box = layout.box()
        #box.operator("graph.sound_bake", icon='IPO')
        box.prop(bake_operator, "threshold")
        box.prop(bake_operator, "release")
        box.prop(bake_operator, 'attack')
        box.prop(bake_operator, "use_additive", icon="PLUS")
        box.prop(bake_operator, "use_accumulate", icon="PLUS")

        row = box.row()

        split = row.split(percentage=0.20)
        split.prop(bake_operator, "use_square")
        split.prop(bake_operator, "sthreshold")